aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--.nant/local.include3
-rw-r--r--OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs4
-rw-r--r--OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs35
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs2
-rw-r--r--OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Capabilities/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/ConsoleClient/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/IPresenceData.cs1
-rw-r--r--OpenSim/Data/IXGroupData.cs71
-rw-r--r--OpenSim/Data/MSSQL/MSSQLPresenceData.cs13
-rw-r--r--OpenSim/Data/MSSQL/MSSQLSimulationData.cs18
-rw-r--r--OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/MSSQL/Resources/RegionStore.migrations8
-rw-r--r--OpenSim/Data/MySQL/MySQLPresenceData.cs14
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs17
-rw-r--r--OpenSim/Data/MySQL/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/MySQL/Resources/RegionStore.migrations8
-rw-r--r--OpenSim/Data/Null/NullGenericDataHandler.cs (renamed from OpenSim/Region/Framework/Scenes/Scripting/NullScriptHost.cs)80
-rw-r--r--OpenSim/Data/Null/NullPresenceData.cs8
-rw-r--r--OpenSim/Data/Null/NullRegionData.cs64
-rw-r--r--OpenSim/Data/Null/NullXGroupData.cs90
-rw-r--r--OpenSim/Data/Null/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/SQLite/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/SQLite/Resources/RegionStore.migrations5
-rw-r--r--OpenSim/Data/SQLite/SQLiteSimulationData.cs19
-rw-r--r--OpenSim/Data/Tests/AssetTests.cs2
-rw-r--r--OpenSim/Data/Tests/BasicDataServiceTest.cs7
-rw-r--r--OpenSim/Data/Tests/PropertyCompareConstraint.cs3
-rw-r--r--OpenSim/Data/Tests/PropertyScrambler.cs3
-rw-r--r--OpenSim/Framework/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Communications/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Console/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Console/CommandConsole.cs10
-rw-r--r--OpenSim/Framework/Console/ConsoleDisplayTable.cs15
-rw-r--r--OpenSim/Framework/Console/ConsoleUtil.cs28
-rw-r--r--OpenSim/Framework/DAMap.cs273
-rw-r--r--OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs508
-rw-r--r--OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/PluginManager.cs563
-rw-r--r--OpenSim/Framework/PrimitiveBaseShape.cs21
-rw-r--r--OpenSim/Framework/RegionInfo.cs27
-rw-r--r--OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Serialization/ArchiveConstants.cs5
-rw-r--r--OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs2
-rw-r--r--OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs2
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs122
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs230
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs12
-rw-r--r--OpenSim/Framework/Servers/HttpServer/JsonRPCMethod.cs (renamed from OpenSim/Region/Framework/Scenes/Scripting/ScriptEngineInterface.cs)12
-rw-r--r--OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs150
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs16
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs1085
-rw-r--r--OpenSim/Framework/Servers/MainServer.cs4
-rw-r--r--OpenSim/Framework/Servers/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs111
-rw-r--r--OpenSim/Framework/Servers/Tests/OSHttpTests.cs8
-rw-r--r--OpenSim/Framework/Servers/Tests/VersionInfoTests.cs3
-rw-r--r--OpenSim/Framework/Servers/VersionInfo.cs2
-rw-r--r--OpenSim/Framework/Tests/AgentCircuitDataTest.cs5
-rw-r--r--OpenSim/Framework/Tests/AnimationTests.cs2
-rw-r--r--OpenSim/Framework/Tests/AssetBaseTest.cs3
-rw-r--r--OpenSim/Framework/Tests/CacheTests.cs3
-rw-r--r--OpenSim/Framework/Tests/LocationTest.cs3
-rw-r--r--OpenSim/Framework/Tests/MundaneFrameworkTests.cs11
-rw-r--r--OpenSim/Framework/Tests/PrimeNumberHelperTests.cs3
-rw-r--r--OpenSim/Framework/Tests/UtilTest.cs2
-rw-r--r--OpenSim/Framework/Util.cs80
-rw-r--r--OpenSim/Region/Application/OpenSim.cs37
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs39
-rw-r--r--OpenSim/Region/ClientStack/ClientStackManager.cs83
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs1
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs21
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs13
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs18
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs41
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs32
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs10
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs138
-rw-r--r--OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs107
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs38
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs67
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs35
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs18
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs317
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs129
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs98
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs13
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs88
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs60
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs39
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Sun/SunModule.cs44
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/WindModule.cs2
-rw-r--r--OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISceneCommandsModule.cs (renamed from OpenSim/Region/Framework/Scenes/Scripting/IScriptHost.cs)27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IXmlRpcRouter.cs1
-rw-r--r--OpenSim/Region/Framework/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs15
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs57
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityManager.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs69
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs464
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs62
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs126
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/Scripting/ScriptEngineLoader.cs119
-rw-r--r--OpenSim/Region/Framework/Scenes/Scripting/ScriptUtils.cs107
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs101
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs83
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs43
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs10
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs200
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs1
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs158
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs41
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs283
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs96
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs15
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs127
-rw-r--r--OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs174
-rwxr-xr-xOpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs19
-rw-r--r--OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs135
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs41
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs255
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs257
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs82
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs6
-rw-r--r--OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs14
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs4
-rw-r--r--OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs235
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs2
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs1885
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs2166
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs654
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs527
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs27
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs48
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs12
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs1216
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs59
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs438
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs87
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs200
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs590
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs725
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs281
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs8
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs959
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs1053
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs448
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs183
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs55
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs181
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs84
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs1015
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs269
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt335
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs150
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/Tests/BulletSimTests.cs56
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/Tests/BulletSimTestsUtil.cs95
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs4
-rw-r--r--OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/Manager/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/Manager/IMesher.cs3
-rwxr-xr-xOpenSim/Region/Physics/Manager/IPhysicsParameters.cs6
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs13
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs2
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs15
-rw-r--r--OpenSim/Region/Physics/Manager/ZeroMesher.cs9
-rw-r--r--OpenSim/Region/Physics/Meshing/Mesh.cs2
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs26
-rw-r--r--OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs5
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs2
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs7
-rw-r--r--OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs3
-rw-r--r--OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/POSPlugin/POSPlugin.cs2
-rw-r--r--OpenSim/Region/Physics/POSPlugin/POSScene.cs4
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Mesh.cs2
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs6
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs6
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs6
-rw-r--r--OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs15
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs43
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs66
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs425
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs70
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs76
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs82
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs52
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs17
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs147
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs73
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs18
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs256
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs514
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs29
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs16
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs21
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs61
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/EventManager.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs126
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs (renamed from OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs)2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs271
-rw-r--r--OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs84
-rw-r--r--OpenSim/Region/UserStatistics/Clients_report.cs27
-rw-r--r--OpenSim/Region/UserStatistics/Default_Report.cs27
-rw-r--r--OpenSim/Region/UserStatistics/IStatsReport.cs1
-rw-r--r--OpenSim/Region/UserStatistics/LogLinesAJAX.cs29
-rw-r--r--OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/UserStatistics/Prototype_distributor.cs31
-rw-r--r--OpenSim/Region/UserStatistics/Sessions_Report.cs5
-rw-r--r--OpenSim/Region/UserStatistics/SimStatsAJAX.cs59
-rw-r--r--OpenSim/Region/UserStatistics/Updater_distributor.cs4
-rw-r--r--OpenSim/Region/UserStatistics/WebStatsModule.cs72
-rw-r--r--OpenSim/Server/Base/CommandManager.cs359
-rw-r--r--OpenSim/Server/Base/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Server/Base/ServerUtils.cs222
-rw-r--r--OpenSim/Server/Base/ServicesServerBase.cs10
-rw-r--r--OpenSim/Server/Handlers/Base/ServerConnector.cs67
-rw-r--r--OpenSim/Server/Handlers/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Server/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Server/ServerMain.cs10
-rw-r--r--OpenSim/Services/AssetService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Base/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Connectors/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs2
-rw-r--r--OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Friends/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/GridService/GridService.cs14
-rw-r--r--OpenSim/Services/GridService/HypergridLinker.cs2
-rw-r--r--OpenSim/Services/GridService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/HypergridService/HGInstantMessageService.cs35
-rw-r--r--OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Interfaces/IOfflineIMService.cs115
-rw-r--r--OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/InventoryService/XInventoryService.cs11
-rw-r--r--OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/UserAccountService/UserAccountService.cs2
-rw-r--r--OpenSim/Tests/Common/Helpers/SceneHelpers.cs2
-rw-r--r--OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs77
-rw-r--r--OpenSim/Tests/Common/Mock/MockScriptEngine.cs214
-rw-r--r--OpenSim/Tests/Common/Mock/TestScene.cs3
-rw-r--r--OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs25
-rw-r--r--OpenSim/Tests/ConfigurationLoaderTest.cs3
-rw-r--r--OpenSim/Tests/Performance/NPCPerformanceTests.cs2
-rw-r--r--OpenSim/Tests/Performance/ObjectPerformanceTests.cs2
-rw-r--r--OpenSim/Tests/Performance/ScriptPerformanceTests.cs2
-rw-r--r--OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tools/Configger/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs2
-rw-r--r--TESTING.txt10
-rw-r--r--ThirdParty/SmartThreadPool/AssemblyInfo.cs2
-rw-r--r--ThirdParty/SmartThreadPool/STPStartInfo.cs14
-rw-r--r--ThirdParty/SmartThreadPool/SmartThreadPool.cs8
-rw-r--r--ThirdPartyLicenses/Bullet-XNA.txt23
-rw-r--r--bin/BulletXNA.dllbin0 -> 610304 bytes
-rw-r--r--bin/BulletXNA.pdbbin0 -> 1963520 bytes
-rw-r--r--bin/HttpServer_OpenSim.pdbbin413184 -> 343552 bytes
-rw-r--r--bin/HttpServer_OpenSim.xml5802
-rwxr-xr-xbin/Mono.Addins.CecilReflector.dllbin364032 -> 290816 bytes
-rwxr-xr-xbin/Mono.Addins.Setup.dllbin103424 -> 135168 bytes
-rwxr-xr-xbin/Mono.Addins.dllbin202752 -> 233472 bytes
-rw-r--r--bin/OpenMetaverse.dll.config2
-rwxr-xr-xbin/OpenSim.exe.config6
-rw-r--r--bin/OpenSim.ini.example41
-rw-r--r--bin/OpenSimDefaults.ini112
-rw-r--r--bin/Regions/Regions.ini.example5
-rw-r--r--bin/Robust.HG.ini.example13
-rw-r--r--bin/Robust.ini.example13
-rw-r--r--bin/config-include/GridCommon.ini.example5
-rw-r--r--bin/data/LICENSE-README-IMPORTANT.txt2
-rw-r--r--bin/data/sim.css85
-rw-r--r--bin/data/sim.html291
-rwxr-xr-xbin/lib32/BulletSim.dllbin551424 -> 546304 bytes
-rwxr-xr-xbin/lib32/libBulletSim.sobin1707321 -> 1695269 bytes
-rwxr-xr-xbin/lib64/BulletSim.dllbin699904 -> 694272 bytes
-rwxr-xr-xbin/lib64/libBulletSim.sobin1844228 -> 1841657 bytes
-rw-r--r--doc/README20
-rw-r--r--doc/doxygen.conf1276
-rw-r--r--prebuild.xml112
-rw-r--r--share/Schemas/SceneObjectPart0.xsd166
-rw-r--r--share/Schemas/SceneObjectPart1.xsd8
-rwxr-xr-xshare/php/generateUserFunction.php46
380 files changed, 24590 insertions, 10539 deletions
diff --git a/.gitignore b/.gitignore
index fae7509..91e9be5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -98,3 +98,5 @@ OpenSim/Region/ScriptEngine/test-results/
98OpenSim/Tests/Common/test-results/ 98OpenSim/Tests/Common/test-results/
99OpenSim/Tests/test-results/ 99OpenSim/Tests/test-results/
100test-results/ 100test-results/
101doc/html
102doc/doxygen.error.log
diff --git a/.nant/local.include b/.nant/local.include
index 5185717..c207944 100644
--- a/.nant/local.include
+++ b/.nant/local.include
@@ -43,10 +43,11 @@
43 <delete dir="${distbindir}/Prebuild"/> 43 <delete dir="${distbindir}/Prebuild"/>
44 <delete dir="${distbindir}/%temp%"/> 44 <delete dir="${distbindir}/%temp%"/>
45 <delete dir="${distbindir}/.nant"/> 45 <delete dir="${distbindir}/.nant"/>
46 <delete dir="${distbindir}/ThirdParty"/>
46 <delete> 47 <delete>
47 <fileset basedir="${distbindir}"> 48 <fileset basedir="${distbindir}">
48 <include name="compile.bat"/> 49 <include name="compile.bat"/>
49 <include name="BUILDING.txt"/> 50 <include name="BUILDING.md"/>
50 <include name="Makefile"/> 51 <include name="Makefile"/>
51 <include name="nant-color"/> 52 <include name="nant-color"/>
52 <include name="OpenSim.*"/> 53 <include name="OpenSim.*"/>
diff --git a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
index 57615ea..b81c1e5 100644
--- a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
@@ -60,7 +60,7 @@ using System.Runtime.InteropServices;
60// 60//
61// You can specify all the values or you can default the Build and Revision Numbers 61// You can specify all the values or you can default the Build and Revision Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63// [assembly: AssemblyVersion("0.7.5.*")] 63// [assembly: AssemblyVersion("0.7.6.*")]
64 64
65[assembly : AssemblyVersion("0.7.5.*")] 65[assembly : AssemblyVersion("0.7.6.*")]
66[assembly : AssemblyFileVersion("0.6.5.0")] \ No newline at end of file 66[assembly : AssemblyFileVersion("0.6.5.0")] \ No newline at end of file
diff --git a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
index 14527d9..be6054d 100644
--- a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
index 8ad948c..3ec7a13 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index 68686c5..aa6203b 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -240,6 +240,11 @@ namespace OpenSim.Capabilities.Handlers
240 } 240 }
241 else 241 else
242 { 242 {
243 // Handle the case where no second range value was given. This is equivalent to requesting
244 // the rest of the entity.
245 if (end == -1)
246 end = int.MaxValue;
247
243 end = Utils.Clamp(end, 0, texture.Data.Length - 1); 248 end = Utils.Clamp(end, 0, texture.Data.Length - 1);
244 start = Utils.Clamp(start, 0, end); 249 start = Utils.Clamp(start, 0, end);
245 int len = end - start + 1; 250 int len = end - start + 1;
@@ -298,15 +303,43 @@ namespace OpenSim.Capabilities.Handlers
298// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length); 303// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
299 } 304 }
300 305
306 /// <summary>
307 /// Parse a range header.
308 /// </summary>
309 /// <remarks>
310 /// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
311 /// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
312 /// Where there is no value, -1 is returned.
313 /// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
314 /// for start.</remarks>
315 /// <returns></returns>
316 /// <param name='header'></param>
317 /// <param name='start'>Start of the range. Undefined if this was not a number.</param>
318 /// <param name='end'>End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.</param>
301 private bool TryParseRange(string header, out int start, out int end) 319 private bool TryParseRange(string header, out int start, out int end)
302 { 320 {
321 start = end = 0;
322
303 if (header.StartsWith("bytes=")) 323 if (header.StartsWith("bytes="))
304 { 324 {
305 string[] rangeValues = header.Substring(6).Split('-'); 325 string[] rangeValues = header.Substring(6).Split('-');
326
306 if (rangeValues.Length == 2) 327 if (rangeValues.Length == 2)
307 { 328 {
308 if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end)) 329 if (!Int32.TryParse(rangeValues[0], out start))
330 return false;
331
332 string rawEnd = rangeValues[1];
333
334 if (rawEnd == "")
335 {
336 end = -1;
337 return true;
338 }
339 else if (Int32.TryParse(rawEnd, out end))
340 {
309 return true; 341 return true;
342 }
310 } 343 }
311 } 344 }
312 345
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
index b6ae41b..217a265 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
@@ -43,7 +43,7 @@ using OpenSim.Tests.Common.Mock;
43namespace OpenSim.Capabilities.Handlers.GetTexture.Tests 43namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class GetTextureHandlerTests 46 public class GetTextureHandlerTests : OpenSimTestCase
47 { 47 {
48 [Test] 48 [Test]
49 public void TestTextureNotFound() 49 public void TestTextureNotFound()
diff --git a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
index a681fb6..4ff5fe1 100644
--- a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Capabilities/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Properties/AssemblyInfo.cs
index 26254f2..f8a9dae 100644
--- a/OpenSim/Capabilities/Properties/AssemblyInfo.cs
+++ b/OpenSim/Capabilities/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/ConsoleClient/Properties/AssemblyInfo.cs b/OpenSim/ConsoleClient/Properties/AssemblyInfo.cs
index c240f90..9c0c784 100644
--- a/OpenSim/ConsoleClient/Properties/AssemblyInfo.cs
+++ b/OpenSim/ConsoleClient/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Data/IPresenceData.cs b/OpenSim/Data/IPresenceData.cs
index b871f56..9ec48b0 100644
--- a/OpenSim/Data/IPresenceData.cs
+++ b/OpenSim/Data/IPresenceData.cs
@@ -53,5 +53,6 @@ namespace OpenSim.Data
53 bool ReportAgent(UUID sessionID, UUID regionID); 53 bool ReportAgent(UUID sessionID, UUID regionID);
54 PresenceData[] Get(string field, string data); 54 PresenceData[] Get(string field, string data);
55 bool Delete(string field, string val); 55 bool Delete(string field, string val);
56 bool VerifyAgent(UUID agentId, UUID secureSessionID);
56 } 57 }
57} 58}
diff --git a/OpenSim/Data/IXGroupData.cs b/OpenSim/Data/IXGroupData.cs
new file mode 100644
index 0000000..2965e8c
--- /dev/null
+++ b/OpenSim/Data/IXGroupData.cs
@@ -0,0 +1,71 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Data
34{
35 public class XGroup
36 {
37 public UUID groupID;
38 public UUID ownerRoleID;
39 public string name;
40 public string charter;
41 public bool showInList;
42 public UUID insigniaID;
43 public int membershipFee;
44 public bool openEnrollment;
45 public bool allowPublish;
46 public bool maturePublish;
47 public UUID founderID;
48 public ulong everyonePowers;
49 public ulong ownersPowers;
50
51 public XGroup Clone()
52 {
53 return (XGroup)MemberwiseClone();
54 }
55 }
56
57 /// <summary>
58 /// Early stub interface for groups data, not final.
59 /// </summary>
60 /// <remarks>
61 /// Currently in-use only for regression test purposes. Needs to be filled out over time.
62 /// </remarks>
63 public interface IXGroupData
64 {
65 bool StoreGroup(XGroup group);
66 XGroup[] GetGroups(string field, string val);
67 XGroup[] GetGroups(string[] fields, string[] vals);
68 bool DeleteGroups(string field, string val);
69 bool DeleteGroups(string[] fields, string[] vals);
70 }
71} \ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/MSSQLPresenceData.cs b/OpenSim/Data/MSSQL/MSSQLPresenceData.cs
index e7b3d9c..deff2ed 100644
--- a/OpenSim/Data/MSSQL/MSSQLPresenceData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLPresenceData.cs
@@ -100,5 +100,18 @@ namespace OpenSim.Data.MSSQL
100 return true; 100 return true;
101 } 101 }
102 102
103 public bool VerifyAgent(UUID agentId, UUID secureSessionID)
104 {
105 PresenceData[] ret = Get("SecureSessionID",
106 secureSessionID.ToString());
107
108 if (ret.Length == 0)
109 return false;
110
111 if(ret[0].UserID != agentId.ToString())
112 return false;
113
114 return true;
115 }
103 } 116 }
104} 117}
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
index 5bb6ec9..f056806 100644
--- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
@@ -351,7 +351,7 @@ IF EXISTS (SELECT UUID FROM prims WHERE UUID = @UUID)
351 ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice, 351 ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice,
352 SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem, 352 SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem,
353 ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches, 353 ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches,
354 LinkNumber = @LinkNumber, MediaURL = @MediaURL 354 LinkNumber = @LinkNumber, MediaURL = @MediaURL, DynAttrs = @DynAttrs
355 WHERE UUID = @UUID 355 WHERE UUID = @UUID
356 END 356 END
357ELSE 357ELSE
@@ -366,7 +366,7 @@ ELSE
366 PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX, 366 PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX,
367 OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ, 367 OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ,
368 ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA, 368 ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA,
369 ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL 369 ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL, DynAttrs
370 ) VALUES ( 370 ) VALUES (
371 @UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask, 371 @UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask,
372 @EveryoneMask, @BaseMask, @PositionX, @PositionY, @PositionZ, @GroupPositionX, @GroupPositionY, @GroupPositionZ, @VelocityX, 372 @EveryoneMask, @BaseMask, @PositionX, @PositionY, @PositionZ, @GroupPositionX, @GroupPositionY, @GroupPositionZ, @VelocityX,
@@ -376,7 +376,7 @@ ELSE
376 @PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX, 376 @PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX,
377 @OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ, 377 @OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ,
378 @ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA, 378 @ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA,
379 @ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL 379 @ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL, @DynAttrs
380 ) 380 )
381 END"; 381 END";
382 382
@@ -1691,6 +1691,11 @@ VALUES
1691 1691
1692 if (!(primRow["MediaURL"] is System.DBNull)) 1692 if (!(primRow["MediaURL"] is System.DBNull))
1693 prim.MediaUrl = (string)primRow["MediaURL"]; 1693 prim.MediaUrl = (string)primRow["MediaURL"];
1694
1695 if (!(primRow["DynAttrs"] is System.DBNull))
1696 prim.DynAttrs = DAMap.FromXml((string)primRow["DynAttrs"]);
1697 else
1698 prim.DynAttrs = new DAMap();
1694 1699
1695 return prim; 1700 return prim;
1696 } 1701 }
@@ -1749,7 +1754,6 @@ VALUES
1749 baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]); 1754 baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]);
1750 } 1755 }
1751 1756
1752
1753 return baseShape; 1757 return baseShape;
1754 } 1758 }
1755 1759
@@ -2086,6 +2090,11 @@ VALUES
2086 parameters.Add(_Database.CreateParameter("PassTouches", 0)); 2090 parameters.Add(_Database.CreateParameter("PassTouches", 0));
2087 parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum)); 2091 parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum));
2088 parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl)); 2092 parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl));
2093
2094 if (prim.DynAttrs.Count > 0)
2095 parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml()));
2096 else
2097 parameters.Add(_Database.CreateParameter("DynAttrs", null));
2089 2098
2090 return parameters.ToArray(); 2099 return parameters.ToArray();
2091 } 2100 }
@@ -2143,7 +2152,6 @@ VALUES
2143 parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml())); 2152 parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml()));
2144 } 2153 }
2145 2154
2146
2147 return parameters.ToArray(); 2155 return parameters.ToArray();
2148 } 2156 }
2149 2157
diff --git a/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs b/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
index 1a67e70..4e96be8 100644
--- a/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.5.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
index 350e548..92cc38a 100644
--- a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
@@ -1148,3 +1148,11 @@ CREATE TABLE [dbo].[regionenvironment](
1148) ON [PRIMARY] 1148) ON [PRIMARY]
1149 1149
1150COMMIT 1150COMMIT
1151
1152:VERSION 38 #---------------- Dynamic attributes
1153
1154BEGIN TRANSACTION
1155
1156ALTER TABLE prims ADD COLUMN DynAttrs TEXT;
1157
1158COMMIT
diff --git a/OpenSim/Data/MySQL/MySQLPresenceData.cs b/OpenSim/Data/MySQL/MySQLPresenceData.cs
index 7808060..3f90639 100644
--- a/OpenSim/Data/MySQL/MySQLPresenceData.cs
+++ b/OpenSim/Data/MySQL/MySQLPresenceData.cs
@@ -95,5 +95,19 @@ namespace OpenSim.Data.MySQL
95 95
96 return true; 96 return true;
97 } 97 }
98
99 public bool VerifyAgent(UUID agentId, UUID secureSessionID)
100 {
101 PresenceData[] ret = Get("SecureSessionID",
102 secureSessionID.ToString());
103
104 if (ret.Length == 0)
105 return false;
106
107 if(ret[0].UserID != agentId.ToString())
108 return false;
109
110 return true;
111 }
98 } 112 }
99} \ No newline at end of file 113} \ No newline at end of file
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index d5a4f46..30ae7a9 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -176,7 +176,7 @@ namespace OpenSim.Data.MySQL
176 "PassCollisions, " + 176 "PassCollisions, " +
177 "LinkNumber, MediaURL, KeyframeMotion, " + 177 "LinkNumber, MediaURL, KeyframeMotion, " +
178 "PhysicsShapeType, Density, GravityModifier, " + 178 "PhysicsShapeType, Density, GravityModifier, " +
179 "Friction, Restitution, Vehicle " + 179 "Friction, Restitution, Vehicle, DynAttrs " +
180 ") values (" + "?UUID, " + 180 ") values (" + "?UUID, " +
181 "?CreationDate, ?Name, ?Text, " + 181 "?CreationDate, ?Name, ?Text, " +
182 "?Description, ?SitName, ?TouchName, " + 182 "?Description, ?SitName, ?TouchName, " +
@@ -211,7 +211,7 @@ namespace OpenSim.Data.MySQL
211 "?CollisionSoundVolume, ?PassTouches, ?PassCollisions, " + 211 "?CollisionSoundVolume, ?PassTouches, ?PassCollisions, " +
212 "?LinkNumber, ?MediaURL, ?KeyframeMotion, " + 212 "?LinkNumber, ?MediaURL, ?KeyframeMotion, " +
213 "?PhysicsShapeType, ?Density, ?GravityModifier, " + 213 "?PhysicsShapeType, ?Density, ?GravityModifier, " +
214 "?Friction, ?Restitution, ?Vehicle)"; 214 "?Friction, ?Restitution, ?Vehicle, ?DynAttrs)";
215 215
216 FillPrimCommand(cmd, prim, obj.UUID, regionUUID); 216 FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
217 217
@@ -228,7 +228,8 @@ namespace OpenSim.Data.MySQL
228 "PathTaperX, PathTaperY, PathTwist, " + 228 "PathTaperX, PathTaperY, PathTwist, " +
229 "PathTwistBegin, ProfileBegin, ProfileEnd, " + 229 "PathTwistBegin, ProfileBegin, ProfileEnd, " +
230 "ProfileCurve, ProfileHollow, Texture, " + 230 "ProfileCurve, ProfileHollow, Texture, " +
231 "ExtraParams, State, Media) values (?UUID, " + 231 "ExtraParams, State, Media) " +
232 "values (?UUID, " +
232 "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " + 233 "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " +
233 "?PCode, ?PathBegin, ?PathEnd, " + 234 "?PCode, ?PathBegin, ?PathEnd, " +
234 "?PathScaleX, ?PathScaleY, " + 235 "?PathScaleX, ?PathScaleY, " +
@@ -1321,6 +1322,11 @@ namespace OpenSim.Data.MySQL
1321 1322
1322 if (!(row["MediaURL"] is System.DBNull)) 1323 if (!(row["MediaURL"] is System.DBNull))
1323 prim.MediaUrl = (string)row["MediaURL"]; 1324 prim.MediaUrl = (string)row["MediaURL"];
1325
1326 if (!(row["DynAttrs"] is System.DBNull))
1327 prim.DynAttrs = DAMap.FromXml((string)row["DynAttrs"]);
1328 else
1329 prim.DynAttrs = new DAMap();
1324 1330
1325 if (!(row["KeyframeMotion"] is DBNull)) 1331 if (!(row["KeyframeMotion"] is DBNull))
1326 { 1332 {
@@ -1731,6 +1737,11 @@ namespace OpenSim.Data.MySQL
1731 cmd.Parameters.AddWithValue("Vehicle", prim.VehicleParams.ToXml2()); 1737 cmd.Parameters.AddWithValue("Vehicle", prim.VehicleParams.ToXml2());
1732 else 1738 else
1733 cmd.Parameters.AddWithValue("Vehicle", String.Empty); 1739 cmd.Parameters.AddWithValue("Vehicle", String.Empty);
1740
1741 if (prim.DynAttrs.Count > 0)
1742 cmd.Parameters.AddWithValue("DynAttrs", prim.DynAttrs.ToXml());
1743 else
1744 cmd.Parameters.AddWithValue("DynAttrs", null);
1734 } 1745 }
1735 1746
1736 /// <summary> 1747 /// <summary>
diff --git a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
index ab3fe36..7bfa28d 100644
--- a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.5.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations
index c4b0832..0be5587 100644
--- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations
@@ -902,3 +902,11 @@ BEGIN;
902CREATE TABLE `regionextra` (`RegionID` char(36) not null, `Name` varchar(32) not null, `value` text, primary key(`RegionID`, `Name`)); 902CREATE TABLE `regionextra` (`RegionID` char(36) not null, `Name` varchar(32) not null, `value` text, primary key(`RegionID`, `Name`));
903 903
904COMMIT; 904COMMIT;
905
906:VERSION 46 #---------------- Dynamic attributes
907
908BEGIN;
909
910ALTER TABLE prims ADD COLUMN DynAttrs TEXT;
911
912COMMIT;
diff --git a/OpenSim/Region/Framework/Scenes/Scripting/NullScriptHost.cs b/OpenSim/Data/Null/NullGenericDataHandler.cs
index d7198f0..dd9d190 100644
--- a/OpenSim/Region/Framework/Scenes/Scripting/NullScriptHost.cs
+++ b/OpenSim/Data/Null/NullGenericDataHandler.cs
@@ -26,66 +26,42 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenMetaverse; 29using System.Collections.Generic;
30using log4net; 30using System.Linq;
31using System.Reflection; 31using System.Reflection;
32using log4net;
33using OpenMetaverse;
32using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Data;
33 36
34namespace OpenSim.Region.Framework.Scenes.Scripting 37namespace OpenSim.Data.Null
35{ 38{
36 public class NullScriptHost : IScriptHost 39 /// <summary>
40 /// Not a proper generic data handler yet - probably needs to actually store the data as well instead of relying
41 /// on descendent classes
42 /// </summary>
43 public class NullGenericDataHandler
37 { 44 {
38 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 protected List<T> Get<T>(string[] fields, string[] vals, List<T> inputEntities)
39
40 private Vector3 m_pos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30);
41
42 public string Name
43 {
44 get { return "Object"; }
45 set { }
46 }
47
48 public string SitName
49 { 46 {
50 get { return String.Empty; } 47 List<T> entities = inputEntities;
51 set { }
52 }
53 48
54 public string TouchName 49 for (int i = 0; i < fields.Length; i++)
55 { 50 {
56 get { return String.Empty; } 51 entities
57 set { } 52 = entities.Where(
58 } 53 e =>
54 {
55 FieldInfo fi = typeof(T).GetField(fields[i]);
56 if (fi == null)
57 throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i]));
59 58
60 public string Description 59 return fi.GetValue(e).ToString() == vals[i];
61 { 60 }
62 get { return String.Empty; } 61 ).ToList();
63 set { } 62 }
64 }
65 63
66 public UUID UUID 64 return entities;
67 {
68 get { return UUID.Zero; }
69 }
70
71 public UUID OwnerID
72 {
73 get { return UUID.Zero; }
74 }
75
76 public UUID CreatorID
77 {
78 get { return UUID.Zero; }
79 }
80
81 public Vector3 AbsolutePosition
82 {
83 get { return m_pos; }
84 }
85
86 public void SetText(string text, Vector3 color, double alpha)
87 {
88 m_log.Warn("Tried to SetText "+text+" on NullScriptHost");
89 } 65 }
90 } 66 }
91} 67} \ No newline at end of file
diff --git a/OpenSim/Data/Null/NullPresenceData.cs b/OpenSim/Data/Null/NullPresenceData.cs
index c06c223..b85b95e 100644
--- a/OpenSim/Data/Null/NullPresenceData.cs
+++ b/OpenSim/Data/Null/NullPresenceData.cs
@@ -222,5 +222,13 @@ namespace OpenSim.Data.Null
222 return true; 222 return true;
223 } 223 }
224 224
225 public bool VerifyAgent(UUID agentId, UUID secureSessionID)
226 {
227 if (Instance != this)
228 return Instance.VerifyAgent(agentId, secureSessionID);
229
230 return false;
231 }
232
225 } 233 }
226} 234}
diff --git a/OpenSim/Data/Null/NullRegionData.cs b/OpenSim/Data/Null/NullRegionData.cs
index b4d701a..f707d98 100644
--- a/OpenSim/Data/Null/NullRegionData.cs
+++ b/OpenSim/Data/Null/NullRegionData.cs
@@ -113,11 +113,14 @@ namespace OpenSim.Data.Null
113 // Find region data 113 // Find region data
114 List<RegionData> ret = new List<RegionData>(); 114 List<RegionData> ret = new List<RegionData>();
115 115
116 foreach (RegionData r in m_regionData.Values) 116 lock (m_regionData)
117 { 117 {
118// m_log.DebugFormat("[NULL REGION DATA]: comparing {0} to {1}", cleanName, r.RegionName.ToLower()); 118 foreach (RegionData r in m_regionData.Values)
119 {
120 // m_log.DebugFormat("[NULL REGION DATA]: comparing {0} to {1}", cleanName, r.RegionName.ToLower());
119 if (queryMatch(r.RegionName.ToLower())) 121 if (queryMatch(r.RegionName.ToLower()))
120 ret.Add(r); 122 ret.Add(r);
123 }
121 } 124 }
122 125
123 if (ret.Count > 0) 126 if (ret.Count > 0)
@@ -133,10 +136,13 @@ namespace OpenSim.Data.Null
133 136
134 List<RegionData> ret = new List<RegionData>(); 137 List<RegionData> ret = new List<RegionData>();
135 138
136 foreach (RegionData r in m_regionData.Values) 139 lock (m_regionData)
137 { 140 {
138 if (r.posX == posX && r.posY == posY) 141 foreach (RegionData r in m_regionData.Values)
139 ret.Add(r); 142 {
143 if (r.posX == posX && r.posY == posY)
144 ret.Add(r);
145 }
140 } 146 }
141 147
142 if (ret.Count > 0) 148 if (ret.Count > 0)
@@ -150,8 +156,11 @@ namespace OpenSim.Data.Null
150 if (m_useStaticInstance && Instance != this) 156 if (m_useStaticInstance && Instance != this)
151 return Instance.Get(regionID, scopeID); 157 return Instance.Get(regionID, scopeID);
152 158
153 if (m_regionData.ContainsKey(regionID)) 159 lock (m_regionData)
154 return m_regionData[regionID]; 160 {
161 if (m_regionData.ContainsKey(regionID))
162 return m_regionData[regionID];
163 }
155 164
156 return null; 165 return null;
157 } 166 }
@@ -163,10 +172,13 @@ namespace OpenSim.Data.Null
163 172
164 List<RegionData> ret = new List<RegionData>(); 173 List<RegionData> ret = new List<RegionData>();
165 174
166 foreach (RegionData r in m_regionData.Values) 175 lock (m_regionData)
167 { 176 {
168 if (r.posX >= startX && r.posX <= endX && r.posY >= startY && r.posY <= endY) 177 foreach (RegionData r in m_regionData.Values)
169 ret.Add(r); 178 {
179 if (r.posX >= startX && r.posX <= endX && r.posY >= startY && r.posY <= endY)
180 ret.Add(r);
181 }
170 } 182 }
171 183
172 return ret; 184 return ret;
@@ -180,7 +192,10 @@ namespace OpenSim.Data.Null
180// m_log.DebugFormat( 192// m_log.DebugFormat(
181// "[NULL REGION DATA]: Storing region {0} {1}, scope {2}", data.RegionName, data.RegionID, data.ScopeID); 193// "[NULL REGION DATA]: Storing region {0} {1}, scope {2}", data.RegionName, data.RegionID, data.ScopeID);
182 194
183 m_regionData[data.RegionID] = data; 195 lock (m_regionData)
196 {
197 m_regionData[data.RegionID] = data;
198 }
184 199
185 return true; 200 return true;
186 } 201 }
@@ -190,10 +205,13 @@ namespace OpenSim.Data.Null
190 if (m_useStaticInstance && Instance != this) 205 if (m_useStaticInstance && Instance != this)
191 return Instance.SetDataItem(regionID, item, value); 206 return Instance.SetDataItem(regionID, item, value);
192 207
193 if (!m_regionData.ContainsKey(regionID)) 208 lock (m_regionData)
194 return false; 209 {
210 if (!m_regionData.ContainsKey(regionID))
211 return false;
195 212
196 m_regionData[regionID].Data[item] = value; 213 m_regionData[regionID].Data[item] = value;
214 }
197 215
198 return true; 216 return true;
199 } 217 }
@@ -205,10 +223,13 @@ namespace OpenSim.Data.Null
205 223
206// m_log.DebugFormat("[NULL REGION DATA]: Deleting region {0}", regionID); 224// m_log.DebugFormat("[NULL REGION DATA]: Deleting region {0}", regionID);
207 225
208 if (!m_regionData.ContainsKey(regionID)) 226 lock (m_regionData)
209 return false; 227 {
228 if (!m_regionData.ContainsKey(regionID))
229 return false;
210 230
211 m_regionData.Remove(regionID); 231 m_regionData.Remove(regionID);
232 }
212 233
213 return true; 234 return true;
214 } 235 }
@@ -238,10 +259,13 @@ namespace OpenSim.Data.Null
238 259
239 List<RegionData> ret = new List<RegionData>(); 260 List<RegionData> ret = new List<RegionData>();
240 261
241 foreach (RegionData r in m_regionData.Values) 262 lock (m_regionData)
242 { 263 {
243 if ((Convert.ToInt32(r.Data["flags"]) & regionFlags) != 0) 264 foreach (RegionData r in m_regionData.Values)
244 ret.Add(r); 265 {
266 if ((Convert.ToInt32(r.Data["flags"]) & regionFlags) != 0)
267 ret.Add(r);
268 }
245 } 269 }
246 270
247 return ret; 271 return ret;
diff --git a/OpenSim/Data/Null/NullXGroupData.cs b/OpenSim/Data/Null/NullXGroupData.cs
new file mode 100644
index 0000000..7a86b9f
--- /dev/null
+++ b/OpenSim/Data/Null/NullXGroupData.cs
@@ -0,0 +1,90 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Linq;
32using System.Reflection;
33using System.Threading;
34using log4net;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Data;
38
39namespace OpenSim.Data.Null
40{
41 public class NullXGroupData : NullGenericDataHandler, IXGroupData
42 {
43// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 private Dictionary<UUID, XGroup> m_groups = new Dictionary<UUID, XGroup>();
46
47 public NullXGroupData(string connectionString, string realm) {}
48
49 public bool StoreGroup(XGroup group)
50 {
51 lock (m_groups)
52 {
53 m_groups[group.groupID] = group.Clone();
54 }
55
56 return true;
57 }
58
59 public XGroup[] GetGroups(string field, string val)
60 {
61 return GetGroups(new string[] { field }, new string[] { val });
62 }
63
64 public XGroup[] GetGroups(string[] fields, string[] vals)
65 {
66 lock (m_groups)
67 {
68 List<XGroup> origGroups = Get<XGroup>(fields, vals, m_groups.Values.ToList());
69
70 return origGroups.Select(g => g.Clone()).ToArray();
71 }
72 }
73
74 public bool DeleteGroups(string field, string val)
75 {
76 return DeleteGroups(new string[] { field }, new string[] { val });
77 }
78
79 public bool DeleteGroups(string[] fields, string[] vals)
80 {
81 lock (m_groups)
82 {
83 XGroup[] groupsToDelete = GetGroups(fields, vals);
84 Array.ForEach(groupsToDelete, g => m_groups.Remove(g.groupID));
85 }
86
87 return true;
88 }
89 }
90} \ No newline at end of file
diff --git a/OpenSim/Data/Null/Properties/AssemblyInfo.cs b/OpenSim/Data/Null/Properties/AssemblyInfo.cs
index 43b0bb3..3931b3d 100644
--- a/OpenSim/Data/Null/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/Null/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.5.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Data/Properties/AssemblyInfo.cs b/OpenSim/Data/Properties/AssemblyInfo.cs
index 0da1a6b..9f342ad 100644
--- a/OpenSim/Data/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.5.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
index c9a8553..ba52f82 100644
--- a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.5.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Data/SQLite/Resources/RegionStore.migrations b/OpenSim/Data/SQLite/Resources/RegionStore.migrations
index e872977..e583dc2 100644
--- a/OpenSim/Data/SQLite/Resources/RegionStore.migrations
+++ b/OpenSim/Data/SQLite/Resources/RegionStore.migrations
@@ -575,3 +575,8 @@ CREATE TABLE `regionenvironment` (
575); 575);
576 576
577COMMIT; 577COMMIT;
578
579:VERSION 27
580BEGIN;
581ALTER TABLE prims ADD COLUMN DynAttrs TEXT;
582COMMIT;
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index 42cd59d..c5a02d0 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -1232,6 +1232,8 @@ namespace OpenSim.Data.SQLite
1232 createCol(prims, "VolumeDetect", typeof(Int16)); 1232 createCol(prims, "VolumeDetect", typeof(Int16));
1233 1233
1234 createCol(prims, "MediaURL", typeof(String)); 1234 createCol(prims, "MediaURL", typeof(String));
1235
1236 createCol(prims, "DynAttrs", typeof(String));
1235 1237
1236 // Add in contraints 1238 // Add in contraints
1237 prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] }; 1239 prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };
@@ -1711,6 +1713,16 @@ namespace OpenSim.Data.SQLite
1711// m_log.DebugFormat("[SQLITE]: MediaUrl type [{0}]", row["MediaURL"].GetType()); 1713// m_log.DebugFormat("[SQLITE]: MediaUrl type [{0}]", row["MediaURL"].GetType());
1712 prim.MediaUrl = (string)row["MediaURL"]; 1714 prim.MediaUrl = (string)row["MediaURL"];
1713 } 1715 }
1716
1717 if (!(row["DynAttrs"] is System.DBNull))
1718 {
1719 //m_log.DebugFormat("[SQLITE]: DynAttrs type [{0}]", row["DynAttrs"].GetType());
1720 prim.DynAttrs = DAMap.FromXml((string)row["DynAttrs"]);
1721 }
1722 else
1723 {
1724 prim.DynAttrs = new DAMap();
1725 }
1714 1726
1715 return prim; 1727 return prim;
1716 } 1728 }
@@ -2133,6 +2145,11 @@ namespace OpenSim.Data.SQLite
2133 row["VolumeDetect"] = 0; 2145 row["VolumeDetect"] = 0;
2134 2146
2135 row["MediaURL"] = prim.MediaUrl; 2147 row["MediaURL"] = prim.MediaUrl;
2148
2149 if (prim.DynAttrs.Count > 0)
2150 row["DynAttrs"] = prim.DynAttrs.ToXml();
2151 else
2152 row["DynAttrs"] = null;
2136 } 2153 }
2137 2154
2138 /// <summary> 2155 /// <summary>
@@ -2392,7 +2409,7 @@ namespace OpenSim.Data.SQLite
2392 2409
2393 if (!(row["Media"] is System.DBNull)) 2410 if (!(row["Media"] is System.DBNull))
2394 s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]); 2411 s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]);
2395 2412
2396 return s; 2413 return s;
2397 } 2414 }
2398 2415
diff --git a/OpenSim/Data/Tests/AssetTests.cs b/OpenSim/Data/Tests/AssetTests.cs
index 1174e2f..8cb2ee0 100644
--- a/OpenSim/Data/Tests/AssetTests.cs
+++ b/OpenSim/Data/Tests/AssetTests.cs
@@ -49,7 +49,7 @@ using OpenSim.Data.SQLite;
49namespace OpenSim.Data.Tests 49namespace OpenSim.Data.Tests
50{ 50{
51 [TestFixture(Description = "Asset store tests (SQLite)")] 51 [TestFixture(Description = "Asset store tests (SQLite)")]
52 public class SQLiteAssetTests : AssetTests<SqliteConnection, SQLiteAssetData> 52 public class SQLiteAssetTests : AssetTests<SqliteConnection, SQLiteAssetData>
53 { 53 {
54 } 54 }
55 55
diff --git a/OpenSim/Data/Tests/BasicDataServiceTest.cs b/OpenSim/Data/Tests/BasicDataServiceTest.cs
index 7d85f0c..69b79bf 100644
--- a/OpenSim/Data/Tests/BasicDataServiceTest.cs
+++ b/OpenSim/Data/Tests/BasicDataServiceTest.cs
@@ -33,6 +33,7 @@ using NUnit.Framework;
33using NUnit.Framework.Constraints; 33using NUnit.Framework.Constraints;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Tests.Common;
36using log4net; 37using log4net;
37using System.Data; 38using System.Data;
38using System.Data.Common; 39using System.Data.Common;
@@ -43,6 +44,12 @@ namespace OpenSim.Data.Tests
43 /// <summary>This is a base class for testing any Data service for any DBMS. 44 /// <summary>This is a base class for testing any Data service for any DBMS.
44 /// Requires NUnit 2.5 or better (to support the generics). 45 /// Requires NUnit 2.5 or better (to support the generics).
45 /// </summary> 46 /// </summary>
47 /// <remarks>
48 /// FIXME: Should extend OpenSimTestCase but compile on mono 2.4.3 currently fails with
49 /// AssetTests`2 : System.MemberAccessException : Cannot create an instance of OpenSim.Data.Tests.AssetTests`2[TConn,TAssetData] because Type.ContainsGenericParameters is true.
50 /// and similar on EstateTests, InventoryTests and RegionTests.
51 /// Runs fine with mono 2.10.8.1, so easiest thing is to wait until min Mono version uplifts.
52 /// </remarks>
46 /// <typeparam name="TConn"></typeparam> 53 /// <typeparam name="TConn"></typeparam>
47 /// <typeparam name="TService"></typeparam> 54 /// <typeparam name="TService"></typeparam>
48 public class BasicDataServiceTest<TConn, TService> 55 public class BasicDataServiceTest<TConn, TService>
diff --git a/OpenSim/Data/Tests/PropertyCompareConstraint.cs b/OpenSim/Data/Tests/PropertyCompareConstraint.cs
index 6c79bda..b99525a 100644
--- a/OpenSim/Data/Tests/PropertyCompareConstraint.cs
+++ b/OpenSim/Data/Tests/PropertyCompareConstraint.cs
@@ -36,6 +36,7 @@ using NUnit.Framework;
36using NUnit.Framework.Constraints; 36using NUnit.Framework.Constraints;
37using OpenMetaverse; 37using OpenMetaverse;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Tests.Common;
39 40
40namespace OpenSim.Data.Tests 41namespace OpenSim.Data.Tests
41{ 42{
@@ -254,7 +255,7 @@ namespace OpenSim.Data.Tests
254 } 255 }
255 256
256 [TestFixture] 257 [TestFixture]
257 public class PropertyCompareConstraintTest 258 public class PropertyCompareConstraintTest : OpenSimTestCase
258 { 259 {
259 public class HasInt 260 public class HasInt
260 { 261 {
diff --git a/OpenSim/Data/Tests/PropertyScrambler.cs b/OpenSim/Data/Tests/PropertyScrambler.cs
index c5d40c2..e0f5862 100644
--- a/OpenSim/Data/Tests/PropertyScrambler.cs
+++ b/OpenSim/Data/Tests/PropertyScrambler.cs
@@ -34,6 +34,7 @@ using System.Text;
34using NUnit.Framework; 34using NUnit.Framework;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Tests.Common;
37 38
38namespace OpenSim.Data.Tests 39namespace OpenSim.Data.Tests
39{ 40{
@@ -158,7 +159,7 @@ namespace OpenSim.Data.Tests
158 } 159 }
159 160
160 [TestFixture] 161 [TestFixture]
161 public class PropertyScramblerTests 162 public class PropertyScramblerTests : OpenSimTestCase
162 { 163 {
163 [Test] 164 [Test]
164 public void TestScramble() 165 public void TestScramble()
diff --git a/OpenSim/Framework/AssemblyInfo.cs b/OpenSim/Framework/AssemblyInfo.cs
index 02986d5..b3db56c 100644
--- a/OpenSim/Framework/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssemblyInfo.cs
@@ -59,5 +59,5 @@ using System.Runtime.InteropServices;
59// Revision 59// Revision
60// 60//
61 61
62[assembly : AssemblyVersion("0.7.5.*")] 62[assembly : AssemblyVersion("0.7.6.*")]
63[assembly : AssemblyFileVersion("0.6.5.0")] \ No newline at end of file 63[assembly : AssemblyFileVersion("0.6.5.0")] \ No newline at end of file
diff --git a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
index 0498ed4..077244d 100644
--- a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
index 6d1c03a..cf575ac 100644
--- a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.5.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
index 0674656..c3b6227 100644
--- a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
index 1095b23..b0d2d67 100644
--- a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Console/AssemblyInfo.cs b/OpenSim/Framework/Console/AssemblyInfo.cs
index 37c7304..c618454 100644
--- a/OpenSim/Framework/Console/AssemblyInfo.cs
+++ b/OpenSim/Framework/Console/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.5.*")] 58[assembly : AssemblyVersion("0.7.6.*")]
diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs
index d703d78..9490013 100644
--- a/OpenSim/Framework/Console/CommandConsole.cs
+++ b/OpenSim/Framework/Console/CommandConsole.cs
@@ -110,10 +110,11 @@ namespace OpenSim.Framework.Console
110 // Remove initial help keyword 110 // Remove initial help keyword
111 helpParts.RemoveAt(0); 111 helpParts.RemoveAt(0);
112 112
113 help.Add(""); // Will become a newline.
114
113 // General help 115 // General help
114 if (helpParts.Count == 0) 116 if (helpParts.Count == 0)
115 { 117 {
116 help.Add(""); // Will become a newline.
117 help.Add(GeneralHelpText); 118 help.Add(GeneralHelpText);
118 help.AddRange(CollectAllCommandsHelp()); 119 help.AddRange(CollectAllCommandsHelp());
119 } 120 }
@@ -129,6 +130,8 @@ namespace OpenSim.Framework.Console
129 help.AddRange(CollectHelp(helpParts)); 130 help.AddRange(CollectHelp(helpParts));
130 } 131 }
131 132
133 help.Add(""); // Will become a newline.
134
132 return help; 135 return help;
133 } 136 }
134 137
@@ -199,14 +202,11 @@ namespace OpenSim.Framework.Console
199 202
200 string descriptiveHelp = commandInfo.descriptive_help; 203 string descriptiveHelp = commandInfo.descriptive_help;
201 204
202 // If we do have some descriptive help then insert a spacing line before and after for readability. 205 // If we do have some descriptive help then insert a spacing line before for readability.
203 if (descriptiveHelp != string.Empty) 206 if (descriptiveHelp != string.Empty)
204 help.Add(string.Empty); 207 help.Add(string.Empty);
205 208
206 help.Add(commandInfo.descriptive_help); 209 help.Add(commandInfo.descriptive_help);
207
208 if (descriptiveHelp != string.Empty)
209 help.Add(string.Empty);
210 } 210 }
211 else 211 else
212 { 212 {
diff --git a/OpenSim/Framework/Console/ConsoleDisplayTable.cs b/OpenSim/Framework/Console/ConsoleDisplayTable.cs
index c620dfe..711a337 100644
--- a/OpenSim/Framework/Console/ConsoleDisplayTable.cs
+++ b/OpenSim/Framework/Console/ConsoleDisplayTable.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Framework.Console
56 public List<ConsoleDisplayTableRow> Rows { get; private set; } 56 public List<ConsoleDisplayTableRow> Rows { get; private set; }
57 57
58 /// <summary> 58 /// <summary>
59 /// Number of spaces to indent the table. 59 /// Number of spaces to indent the whole table.
60 /// </summary> 60 /// </summary>
61 public int Indent { get; set; } 61 public int Indent { get; set; }
62 62
@@ -84,7 +84,7 @@ namespace OpenSim.Framework.Console
84 Columns.Add(new ConsoleDisplayTableColumn(name, width)); 84 Columns.Add(new ConsoleDisplayTableColumn(name, width));
85 } 85 }
86 86
87 public void AddRow(params string[] cells) 87 public void AddRow(params object[] cells)
88 { 88 {
89 Rows.Add(new ConsoleDisplayTableRow(cells)); 89 Rows.Add(new ConsoleDisplayTableRow(cells));
90 } 90 }
@@ -113,7 +113,8 @@ namespace OpenSim.Framework.Console
113 113
114 for (int i = 0; i < Columns.Count; i++) 114 for (int i = 0; i < Columns.Count; i++)
115 { 115 {
116 formatSb.Append(' ', TableSpacing); 116 if (i != 0)
117 formatSb.Append(' ', TableSpacing);
117 118
118 // Can only do left formatting for now 119 // Can only do left formatting for now
119 formatSb.AppendFormat("{{{0},-{1}}}", i, Columns[i].Width); 120 formatSb.AppendFormat("{{{0},-{1}}}", i, Columns[i].Width);
@@ -139,16 +140,16 @@ namespace OpenSim.Framework.Console
139 140
140 public struct ConsoleDisplayTableRow 141 public struct ConsoleDisplayTableRow
141 { 142 {
142 public List<string> Cells { get; private set; } 143 public List<object> Cells { get; private set; }
143 144
144 public ConsoleDisplayTableRow(List<string> cells) : this() 145 public ConsoleDisplayTableRow(List<object> cells) : this()
145 { 146 {
146 Cells = cells; 147 Cells = cells;
147 } 148 }
148 149
149 public ConsoleDisplayTableRow(params string[] cells) : this() 150 public ConsoleDisplayTableRow(params object[] cells) : this()
150 { 151 {
151 Cells = new List<string>(cells); 152 Cells = new List<object>(cells);
152 } 153 }
153 } 154 }
154} \ No newline at end of file 155} \ No newline at end of file
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs
index 16a63e0..dff956a 100644
--- a/OpenSim/Framework/Console/ConsoleUtil.cs
+++ b/OpenSim/Framework/Console/ConsoleUtil.cs
@@ -97,7 +97,7 @@ namespace OpenSim.Framework.Console
97 if (!UUID.TryParse(rawUuid, out uuid)) 97 if (!UUID.TryParse(rawUuid, out uuid))
98 { 98 {
99 if (console != null) 99 if (console != null)
100 console.OutputFormat("{0} is not a valid uuid", rawUuid); 100 console.OutputFormat("ERROR: {0} is not a valid uuid", rawUuid);
101 101
102 return false; 102 return false;
103 } 103 }
@@ -110,7 +110,7 @@ namespace OpenSim.Framework.Console
110 if (!uint.TryParse(rawLocalId, out localId)) 110 if (!uint.TryParse(rawLocalId, out localId))
111 { 111 {
112 if (console != null) 112 if (console != null)
113 console.OutputFormat("{0} is not a valid local id", localId); 113 console.OutputFormat("ERROR: {0} is not a valid local id", localId);
114 114
115 return false; 115 return false;
116 } 116 }
@@ -118,7 +118,7 @@ namespace OpenSim.Framework.Console
118 if (localId == 0) 118 if (localId == 0)
119 { 119 {
120 if (console != null) 120 if (console != null)
121 console.OutputFormat("{0} is not a valid local id - it must be greater than 0", localId); 121 console.OutputFormat("ERROR: {0} is not a valid local id - it must be greater than 0", localId);
122 122
123 return false; 123 return false;
124 } 124 }
@@ -150,10 +150,30 @@ namespace OpenSim.Framework.Console
150 } 150 }
151 151
152 if (console != null) 152 if (console != null)
153 console.OutputFormat("{0} is not a valid UUID or local id", rawId); 153 console.OutputFormat("ERROR: {0} is not a valid UUID or local id", rawId);
154 154
155 return false; 155 return false;
156 } 156 }
157
158 /// <summary>
159 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
160 /// </summary>
161 /// <param name='console'>Can be null if no console is available.</param>
162 /// <param name='rawConsoleVector'>/param>
163 /// <param name='vector'></param>
164 /// <returns></returns>
165 public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i)
166 {
167 if (!int.TryParse(rawConsoleInt, out i))
168 {
169 if (console != null)
170 console.OutputFormat("ERROR: {0} is not a valid integer", rawConsoleInt);
171
172 return false;
173 }
174
175 return true;
176 }
157 177
158 /// <summary> 178 /// <summary>
159 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 179 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
diff --git a/OpenSim/Framework/DAMap.cs b/OpenSim/Framework/DAMap.cs
new file mode 100644
index 0000000..64cea77
--- /dev/null
+++ b/OpenSim/Framework/DAMap.cs
@@ -0,0 +1,273 @@
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.IO;
32using System.Text;
33using System.Xml;
34using System.Xml.Schema;
35using System.Xml.Serialization;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38
39namespace OpenSim.Framework
40{
41 /// <summary>
42 /// This class stores and retrieves dynamic attributes.
43 /// </summary>
44 /// <remarks>
45 /// Modules that want to use dynamic attributes need to do so in a private data store
46 /// which is accessed using a unique name. DAMap provides access to the data stores,
47 /// each of which is an OSDMap. Modules are free to store any type of data they want
48 /// within their data store. However, avoid storing large amounts of data because that
49 /// would slow down database access.
50 /// </remarks>
51 public class DAMap : IDictionary<string, OSDMap>, IXmlSerializable
52 {
53 private static readonly int MIN_STORE_NAME_LENGTH = 4;
54
55 protected OSDMap m_map;
56
57 public DAMap() { m_map = new OSDMap(); }
58
59 public XmlSchema GetSchema() { return null; }
60
61 public static DAMap FromXml(string rawXml)
62 {
63 DAMap map = new DAMap();
64 map.ReadXml(rawXml);
65 return map;
66 }
67
68 public void ReadXml(string rawXml)
69 {
70 // System.Console.WriteLine("Trying to deserialize [{0}]", rawXml);
71
72 lock (this)
73 m_map = (OSDMap)OSDParser.DeserializeLLSDXml(rawXml);
74 }
75
76 // WARNING: this is temporary for experimentation only, it will be removed!!!!
77 public OSDMap TopLevelMap
78 {
79 get { return m_map; }
80 set { m_map = value; }
81 }
82
83
84 public void ReadXml(XmlReader reader)
85 {
86 ReadXml(reader.ReadInnerXml());
87 }
88
89 public string ToXml()
90 {
91 lock (this)
92 return OSDParser.SerializeLLSDXmlString(m_map);
93 }
94
95 public void WriteXml(XmlWriter writer)
96 {
97 writer.WriteRaw(ToXml());
98 }
99
100 public void CopyFrom(DAMap other)
101 {
102 // Deep copy
103
104 string data = null;
105 lock (other)
106 {
107 if (other.Count > 0)
108 {
109 data = OSDParser.SerializeLLSDXmlString(other.m_map);
110 }
111 }
112
113 lock (this)
114 {
115 if (data == null)
116 Clear();
117 else
118 m_map = (OSDMap)OSDParser.DeserializeLLSDXml(data);
119 }
120 }
121
122 /// <summary>
123 /// Returns the number of data stores.
124 /// </summary>
125 public int Count { get { lock (this) { return m_map.Count; } } }
126
127 public bool IsReadOnly { get { return false; } }
128
129 /// <summary>
130 /// Returns the names of the data stores.
131 /// </summary>
132 public ICollection<string> Keys { get { lock (this) { return m_map.Keys; } } }
133
134 /// <summary>
135 /// Returns all the data stores.
136 /// </summary>
137 public ICollection<OSDMap> Values
138 {
139 get
140 {
141 lock (this)
142 {
143 List<OSDMap> stores = new List<OSDMap>(m_map.Count);
144 foreach (OSD llsd in m_map.Values)
145 stores.Add((OSDMap)llsd);
146 return stores;
147 }
148 }
149 }
150
151 /// <summary>
152 /// Gets or sets one data store.
153 /// </summary>
154 /// <param name="key">Store name</param>
155 /// <returns></returns>
156 public OSDMap this[string key]
157 {
158 get
159 {
160 OSD llsd;
161
162 lock (this)
163 {
164 if (m_map.TryGetValue(key, out llsd))
165 return (OSDMap)llsd;
166 else
167 return null;
168 }
169 }
170
171 set
172 {
173 ValidateKey(key);
174 lock (this)
175 m_map[key] = value;
176 }
177 }
178
179 /// <summary>
180 /// Validate the key used for storing separate data stores.
181 /// </summary>
182 /// <param name='key'></param>
183 private static void ValidateKey(string key)
184 {
185 if (key.Length < MIN_STORE_NAME_LENGTH)
186 throw new Exception("Minimum store name length is " + MIN_STORE_NAME_LENGTH);
187 }
188
189 public bool ContainsKey(string key)
190 {
191 lock (this)
192 return m_map.ContainsKey(key);
193 }
194
195 public void Add(string key, OSDMap store)
196 {
197 ValidateKey(key);
198 lock (this)
199 m_map.Add(key, store);
200 }
201
202 public void Add(KeyValuePair<string, OSDMap> kvp)
203 {
204 ValidateKey(kvp.Key);
205 lock (this)
206 m_map.Add(kvp.Key, kvp.Value);
207 }
208
209 public bool Remove(string key)
210 {
211 lock (this)
212 return m_map.Remove(key);
213 }
214
215 public bool TryGetValue(string key, out OSDMap store)
216 {
217 lock (this)
218 {
219 OSD llsd;
220 if (m_map.TryGetValue(key, out llsd))
221 {
222 store = (OSDMap)llsd;
223 return true;
224 }
225 else
226 {
227 store = null;
228 return false;
229 }
230 }
231 }
232
233 public void Clear()
234 {
235 lock (this)
236 m_map.Clear();
237 }
238
239 public bool Contains(KeyValuePair<string, OSDMap> kvp)
240 {
241 lock (this)
242 return m_map.ContainsKey(kvp.Key);
243 }
244
245 public void CopyTo(KeyValuePair<string, OSDMap>[] array, int index)
246 {
247 throw new NotImplementedException();
248 }
249
250 public bool Remove(KeyValuePair<string, OSDMap> kvp)
251 {
252 lock (this)
253 return m_map.Remove(kvp.Key);
254 }
255
256 public System.Collections.IDictionaryEnumerator GetEnumerator()
257 {
258 lock (this)
259 return m_map.GetEnumerator();
260 }
261
262 IEnumerator<KeyValuePair<string, OSDMap>> IEnumerable<KeyValuePair<string, OSDMap>>.GetEnumerator()
263 {
264 return null;
265 }
266
267 IEnumerator IEnumerable.GetEnumerator()
268 {
269 lock (this)
270 return m_map.GetEnumerator();
271 }
272 }
273} \ No newline at end of file
diff --git a/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs b/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs
new file mode 100644
index 0000000..9056548
--- /dev/null
+++ b/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs
@@ -0,0 +1,508 @@
1/*
2 * Copyright (c) 2008, openmetaverse.org, http://opensimulator.org/
3 * All rights reserved.
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 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the openmetaverse.org nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27using System;
28using System.Threading;
29using System.Collections.Generic;
30
31namespace OpenSim.Framework
32{
33 /// <summary>
34 /// A double dictionary that is thread abort safe.
35 /// </summary>
36 /// <remarks>
37 /// This adapts OpenMetaverse.DoubleDictionary to be thread-abort safe by acquiring ReaderWriterLockSlim within
38 /// a finally section (which can't be interrupted by Thread.Abort()).
39 /// </remarks>
40 public class DoubleDictionaryThreadAbortSafe<TKey1, TKey2, TValue>
41 {
42 Dictionary<TKey1, TValue> Dictionary1;
43 Dictionary<TKey2, TValue> Dictionary2;
44 ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
45
46 public DoubleDictionaryThreadAbortSafe()
47 {
48 Dictionary1 = new Dictionary<TKey1,TValue>();
49 Dictionary2 = new Dictionary<TKey2,TValue>();
50 }
51
52 public DoubleDictionaryThreadAbortSafe(int capacity)
53 {
54 Dictionary1 = new Dictionary<TKey1, TValue>(capacity);
55 Dictionary2 = new Dictionary<TKey2, TValue>(capacity);
56 }
57
58 public void Add(TKey1 key1, TKey2 key2, TValue value)
59 {
60 bool gotLock = false;
61
62 try
63 {
64 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
65 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
66 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
67 try {}
68 finally
69 {
70 rwLock.EnterWriteLock();
71 gotLock = true;
72 }
73
74 if (Dictionary1.ContainsKey(key1))
75 {
76 if (!Dictionary2.ContainsKey(key2))
77 throw new ArgumentException("key1 exists in the dictionary but not key2");
78 }
79 else if (Dictionary2.ContainsKey(key2))
80 {
81 if (!Dictionary1.ContainsKey(key1))
82 throw new ArgumentException("key2 exists in the dictionary but not key1");
83 }
84
85 Dictionary1[key1] = value;
86 Dictionary2[key2] = value;
87 }
88 finally
89 {
90 if (gotLock)
91 rwLock.ExitWriteLock();
92 }
93 }
94
95 public bool Remove(TKey1 key1, TKey2 key2)
96 {
97 bool success;
98 bool gotLock = false;
99
100 try
101 {
102 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
103 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
104 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
105 try {}
106 finally
107 {
108 rwLock.EnterWriteLock();
109 gotLock = true;
110 }
111
112 Dictionary1.Remove(key1);
113 success = Dictionary2.Remove(key2);
114 }
115 finally
116 {
117 if (gotLock)
118 rwLock.ExitWriteLock();
119 }
120
121 return success;
122 }
123
124 public bool Remove(TKey1 key1)
125 {
126 bool found = false;
127 bool gotLock = false;
128
129 try
130 {
131 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
132 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
133 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
134 try {}
135 finally
136 {
137 rwLock.EnterWriteLock();
138 gotLock = true;
139 }
140
141 // This is an O(n) operation!
142 TValue value;
143 if (Dictionary1.TryGetValue(key1, out value))
144 {
145 foreach (KeyValuePair<TKey2, TValue> kvp in Dictionary2)
146 {
147 if (kvp.Value.Equals(value))
148 {
149 Dictionary1.Remove(key1);
150 Dictionary2.Remove(kvp.Key);
151 found = true;
152 break;
153 }
154 }
155 }
156 }
157 finally
158 {
159 if (gotLock)
160 rwLock.ExitWriteLock();
161 }
162
163 return found;
164 }
165
166 public bool Remove(TKey2 key2)
167 {
168 bool found = false;
169 bool gotLock = false;
170
171 try
172 {
173 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
174 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
175 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
176 try {}
177 finally
178 {
179 rwLock.EnterWriteLock();
180 gotLock = true;
181 }
182
183 // This is an O(n) operation!
184 TValue value;
185 if (Dictionary2.TryGetValue(key2, out value))
186 {
187 foreach (KeyValuePair<TKey1, TValue> kvp in Dictionary1)
188 {
189 if (kvp.Value.Equals(value))
190 {
191 Dictionary2.Remove(key2);
192 Dictionary1.Remove(kvp.Key);
193 found = true;
194 break;
195 }
196 }
197 }
198 }
199 finally
200 {
201 if (gotLock)
202 rwLock.ExitWriteLock();
203 }
204
205 return found;
206 }
207
208 public void Clear()
209 {
210 bool gotLock = false;
211
212 try
213 {
214 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
215 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
216 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
217 try {}
218 finally
219 {
220 rwLock.EnterWriteLock();
221 gotLock = true;
222 }
223
224 Dictionary1.Clear();
225 Dictionary2.Clear();
226 }
227 finally
228 {
229 if (gotLock)
230 rwLock.ExitWriteLock();
231 }
232 }
233
234 public int Count
235 {
236 get { return Dictionary1.Count; }
237 }
238
239 public bool ContainsKey(TKey1 key)
240 {
241 return Dictionary1.ContainsKey(key);
242 }
243
244 public bool ContainsKey(TKey2 key)
245 {
246 return Dictionary2.ContainsKey(key);
247 }
248
249 public bool TryGetValue(TKey1 key, out TValue value)
250 {
251 bool success;
252 bool gotLock = false;
253
254 try
255 {
256 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
257 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
258 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
259 try {}
260 finally
261 {
262 rwLock.EnterReadLock();
263 gotLock = true;
264 }
265
266 success = Dictionary1.TryGetValue(key, out value);
267 }
268 finally
269 {
270 if (gotLock)
271 rwLock.ExitReadLock();
272 }
273
274 return success;
275 }
276
277 public bool TryGetValue(TKey2 key, out TValue value)
278 {
279 bool success;
280 bool gotLock = false;
281
282 try
283 {
284 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
285 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
286 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
287 try {}
288 finally
289 {
290 rwLock.EnterReadLock();
291 gotLock = true;
292 }
293
294 success = Dictionary2.TryGetValue(key, out value);
295 }
296 finally
297 {
298 if (gotLock)
299 rwLock.ExitReadLock();
300 }
301
302 return success;
303 }
304
305 public void ForEach(Action<TValue> action)
306 {
307 bool gotLock = false;
308
309 try
310 {
311 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
312 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
313 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
314 try {}
315 finally
316 {
317 rwLock.EnterReadLock();
318 gotLock = true;
319 }
320
321 foreach (TValue value in Dictionary1.Values)
322 action(value);
323 }
324 finally
325 {
326 if (gotLock)
327 rwLock.ExitReadLock();
328 }
329 }
330
331 public void ForEach(Action<KeyValuePair<TKey1, TValue>> action)
332 {
333 bool gotLock = false;
334
335 try
336 {
337 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
338 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
339 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
340 try {}
341 finally
342 {
343 rwLock.EnterReadLock();
344 gotLock = true;
345 }
346
347 foreach (KeyValuePair<TKey1, TValue> entry in Dictionary1)
348 action(entry);
349 }
350 finally
351 {
352 if (gotLock)
353 rwLock.ExitReadLock();
354 }
355 }
356
357 public void ForEach(Action<KeyValuePair<TKey2, TValue>> action)
358 {
359 bool gotLock = false;
360
361 try
362 {
363 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
364 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
365 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
366 try {}
367 finally
368 {
369 rwLock.EnterReadLock();
370 gotLock = true;
371 }
372
373 foreach (KeyValuePair<TKey2, TValue> entry in Dictionary2)
374 action(entry);
375 }
376 finally
377 {
378 if (gotLock)
379 rwLock.ExitReadLock();
380 }
381 }
382
383 public TValue FindValue(Predicate<TValue> predicate)
384 {
385 bool gotLock = false;
386
387 try
388 {
389 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
390 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
391 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
392 try {}
393 finally
394 {
395 rwLock.EnterReadLock();
396 gotLock = true;
397 }
398
399 foreach (TValue value in Dictionary1.Values)
400 {
401 if (predicate(value))
402 return value;
403 }
404 }
405 finally
406 {
407 if (gotLock)
408 rwLock.ExitReadLock();
409 }
410
411 return default(TValue);
412 }
413
414 public IList<TValue> FindAll(Predicate<TValue> predicate)
415 {
416 IList<TValue> list = new List<TValue>();
417 bool gotLock = false;
418
419 try
420 {
421 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
422 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
423 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
424 try {}
425 finally
426 {
427 rwLock.EnterReadLock();
428 gotLock = true;
429 }
430
431 foreach (TValue value in Dictionary1.Values)
432 {
433 if (predicate(value))
434 list.Add(value);
435 }
436 }
437 finally
438 {
439 if (gotLock)
440 rwLock.ExitReadLock();
441 }
442
443 return list;
444 }
445
446 public int RemoveAll(Predicate<TValue> predicate)
447 {
448 IList<TKey1> list = new List<TKey1>();
449 bool gotUpgradeableLock = false;
450
451 try
452 {
453 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
454 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
455 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
456 try {}
457 finally
458 {
459 rwLock.EnterUpgradeableReadLock();
460 gotUpgradeableLock = true;
461 }
462
463 foreach (KeyValuePair<TKey1, TValue> kvp in Dictionary1)
464 {
465 if (predicate(kvp.Value))
466 list.Add(kvp.Key);
467 }
468
469 IList<TKey2> list2 = new List<TKey2>(list.Count);
470 foreach (KeyValuePair<TKey2, TValue> kvp in Dictionary2)
471 {
472 if (predicate(kvp.Value))
473 list2.Add(kvp.Key);
474 }
475
476 bool gotWriteLock = false;
477
478 try
479 {
480 try {}
481 finally
482 {
483 rwLock.EnterUpgradeableReadLock();
484 gotWriteLock = true;
485 }
486
487 for (int i = 0; i < list.Count; i++)
488 Dictionary1.Remove(list[i]);
489
490 for (int i = 0; i < list2.Count; i++)
491 Dictionary2.Remove(list2[i]);
492 }
493 finally
494 {
495 if (gotWriteLock)
496 rwLock.ExitWriteLock();
497 }
498 }
499 finally
500 {
501 if (gotUpgradeableLock)
502 rwLock.ExitUpgradeableReadLock();
503 }
504
505 return list.Count;
506 }
507 }
508} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
index 1f2bb40..bb83db1 100644
--- a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/PluginManager.cs b/OpenSim/Framework/PluginManager.cs
new file mode 100644
index 0000000..00263f5
--- /dev/null
+++ b/OpenSim/Framework/PluginManager.cs
@@ -0,0 +1,563 @@
1
2/*
3 * Copyright (c) Contributors, http://opensimulator.org/
4 * See CONTRIBUTORS.TXT for a full list of copyright holders.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the OpenSimulator Project nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29
30using System;
31using System.Text;
32using System.Linq;
33using System.Collections;
34using System.Collections.Generic;
35using System.Collections.ObjectModel;
36using Mono.Addins;
37using Mono.Addins.Setup;
38using Mono.Addins.Description;
39using OpenSim.Framework;
40
41
42namespace OpenSim.Framework
43{
44 /// <summary>
45 /// Manager for registries and plugins
46 /// </summary>
47 public class PluginManager : SetupService
48 {
49 public AddinRegistry PluginRegistry;
50
51 public PluginManager(AddinRegistry registry): base (registry)
52 {
53 PluginRegistry = registry;
54
55 }
56
57 /// <summary>
58 /// Installs the plugin.
59 /// </summary>
60 /// <returns>
61 /// The plugin.
62 /// </returns>
63 /// <param name='args'>
64 /// Arguments.
65 /// </param>
66 public bool InstallPlugin(int ndx, out Dictionary<string, object> result)
67 {
68 Dictionary<string, object> res = new Dictionary<string, object>();
69
70 PackageCollection pack = new PackageCollection();
71 PackageCollection toUninstall;
72 DependencyCollection unresolved;
73
74 IProgressStatus ps = new ConsoleProgressStatus(false);
75
76 AddinRepositoryEntry[] available = GetSortedAvailbleAddins();
77
78 if (ndx > (available.Length - 1))
79 {
80 MainConsole.Instance.Output("Selection out of range");
81 result = res;
82 return false;
83 }
84
85 AddinRepositoryEntry aentry = available[ndx];
86
87 Package p = Package.FromRepository(aentry);
88 pack.Add(p);
89
90 ResolveDependencies(ps, pack, out toUninstall, out unresolved);
91
92 // Attempt to install the plugin disabled
93 if (Install(ps, pack) == true)
94 {
95 MainConsole.Instance.Output("Ignore the following error...");
96 PluginRegistry.Update(ps);
97 Addin addin = PluginRegistry.GetAddin(aentry.Addin.Id);
98 PluginRegistry.DisableAddin(addin.Id);
99 addin.Enabled = false;
100
101 MainConsole.Instance.Output("Installation Success");
102 ListInstalledAddins(out res);
103 result = res;
104 return true;
105 }
106 else
107 {
108 MainConsole.Instance.Output("Installation Failed");
109 result = res;
110 return false;
111 }
112 }
113
114 // Remove plugin
115 /// <summary>
116 /// Uns the install.
117 /// </summary>
118 /// <param name='args'>
119 /// Arguments.
120 /// </param>
121 public void UnInstall(int ndx)
122 {
123 Addin[] addins = GetSortedAddinList("RobustPlugin");
124
125 if (ndx > (addins.Length -1))
126 {
127 MainConsole.Instance.Output("Selection out of range");
128 return;
129 }
130
131 Addin addin = addins[ndx];
132 MainConsole.Instance.OutputFormat("Uninstalling plugin {0}", addin.Id);
133 AddinManager.Registry.DisableAddin(addin.Id);
134 addin.Enabled = false;
135 IProgressStatus ps = new ConsoleProgressStatus(false);
136 Uninstall(ps, addin.Id);
137 MainConsole.Instance.Output("Uninstall Success - restart to complete operation");
138 return;
139 }
140
141 /// <summary>
142 /// Checks the installed.
143 /// </summary>
144 /// <returns>
145 /// The installed.
146 /// </returns>
147 public string CheckInstalled()
148 {
149 return "CheckInstall";
150 }
151
152 /// <summary>
153 /// Lists the installed addins.
154 /// </summary>
155 /// <param name='result'>
156 /// Result.
157 /// </param>
158 public void ListInstalledAddins(out Dictionary<string, object> result)
159 {
160 Dictionary<string, object> res = new Dictionary<string, object>();
161
162 Addin[] addins = GetSortedAddinList("RobustPlugin");
163 if(addins.Count() < 1)
164 {
165 MainConsole.Instance.Output("Error!");
166 }
167 int count = 0;
168 foreach (Addin addin in addins)
169 {
170 Dictionary<string, object> r = new Dictionary<string, object>();
171 r["enabled"] = addin.Enabled == true ? true : false;
172 r["name"] = addin.LocalId;
173 r["version"] = addin.Version;
174
175 res.Add(count.ToString(), r);
176
177 count++;
178 }
179 result = res;
180 return;
181 }
182
183 // List compatible plugins in registered repositories
184 /// <summary>
185 /// Lists the available.
186 /// </summary>
187 /// <param name='result'>
188 /// Result.
189 /// </param>
190 public void ListAvailable(out Dictionary<string, object> result)
191 {
192 Dictionary<string, object> res = new Dictionary<string, object>();
193
194 AddinRepositoryEntry[] addins = GetSortedAvailbleAddins();
195
196 int count = 0;
197 foreach (AddinRepositoryEntry addin in addins)
198 {
199 Dictionary<string, object> r = new Dictionary<string, object>();
200 r["name"] = addin.Addin.Name;
201 r["version"] = addin.Addin.Version;
202 r["repository"] = addin.RepositoryName;
203
204 res.Add(count.ToString(), r);
205 count++;
206 }
207 result = res;
208 return;
209 }
210
211 // List available updates ** 1
212 /// <summary>
213 /// Lists the updates.
214 /// </summary>
215 public void ListUpdates()
216 {
217 IProgressStatus ps = new ConsoleProgressStatus(true);
218 Console.WriteLine ("Looking for updates...");
219 Repositories.UpdateAllRepositories (ps);
220 Console.WriteLine ("Available add-in updates:");
221 bool found = false;
222 AddinRepositoryEntry[] entries = Repositories.GetAvailableUpdates();
223
224 foreach (AddinRepositoryEntry entry in entries)
225 {
226 Console.WriteLine(String.Format("{0}",entry.Addin.Id));
227 }
228 }
229
230 // Sync to repositories
231 /// <summary>
232 /// Update this instance.
233 /// </summary>
234 public string Update()
235 {
236 IProgressStatus ps = new ConsoleProgressStatus(true);
237 Repositories.UpdateAllRepositories(ps);
238 return "Update";
239 }
240
241 // Register a repository
242 /// <summary>
243 /// Register a repository with our server.
244 /// </summary>
245 /// <returns>
246 /// result of the action
247 /// </returns>
248 /// <param name='repo'>
249 /// The URL of the repository we want to add
250 /// </param>
251 public bool AddRepository(string repo)
252 {
253 Repositories.RegisterRepository(null, repo, true);
254 PluginRegistry.Rebuild(null);
255
256 return true;
257 }
258
259 /// <summary>
260 /// Gets the repository.
261 /// </summary>
262 public void GetRepository()
263 {
264 Repositories.UpdateAllRepositories(new ConsoleProgressStatus(false));
265 }
266
267 // Remove a repository from the list
268 /// <summary>
269 /// Removes the repository.
270 /// </summary>
271 /// <param name='args'>
272 /// Arguments.
273 /// </param>
274 public void RemoveRepository(string[] args)
275 {
276 AddinRepository[] reps = Repositories.GetRepositories();
277 Array.Sort(reps, (r1,r2) => r1.Title.CompareTo(r2.Title));
278 if (reps.Length == 0)
279 {
280 MainConsole.Instance.Output("No repositories have been registered.");
281 return;
282 }
283
284 int n = Convert.ToInt16(args[2]);
285 if (n > (reps.Length -1))
286 {
287 MainConsole.Instance.Output("Selection out of range");
288 return;
289 }
290
291 AddinRepository rep = reps[n];
292 Repositories.RemoveRepository(rep.Url);
293 return;
294 }
295
296 // Enable repository
297 /// <summary>
298 /// Enables the repository.
299 /// </summary>
300 /// <param name='args'>
301 /// Arguments.
302 /// </param>
303 public void EnableRepository(string[] args)
304 {
305 AddinRepository[] reps = Repositories.GetRepositories();
306 Array.Sort(reps, (r1,r2) => r1.Title.CompareTo(r2.Title));
307 if (reps.Length == 0)
308 {
309 MainConsole.Instance.Output("No repositories have been registered.");
310 return;
311 }
312
313 int n = Convert.ToInt16(args[2]);
314 if (n > (reps.Length -1))
315 {
316 MainConsole.Instance.Output("Selection out of range");
317 return;
318 }
319
320 AddinRepository rep = reps[n];
321 Repositories.SetRepositoryEnabled(rep.Url, true);
322 return;
323 }
324
325 // Disable a repository
326 /// <summary>
327 /// Disables the repository.
328 /// </summary>
329 /// <param name='args'>
330 /// Arguments.
331 /// </param>
332 public void DisableRepository(string[] args)
333 {
334 AddinRepository[] reps = Repositories.GetRepositories();
335 Array.Sort(reps, (r1,r2) => r1.Title.CompareTo(r2.Title));
336 if (reps.Length == 0)
337 {
338 MainConsole.Instance.Output("No repositories have been registered.");
339 return;
340 }
341
342 int n = Convert.ToInt16(args[2]);
343 if (n > (reps.Length -1))
344 {
345 MainConsole.Instance.Output("Selection out of range");
346 return;
347 }
348
349 AddinRepository rep = reps[n];
350 Repositories.SetRepositoryEnabled(rep.Url, false);
351 return;
352 }
353
354 // List registered repositories
355 /// <summary>
356 /// Lists the repositories.
357 /// </summary>
358 /// <param name='result'>
359 /// Result.
360 /// </param>
361 public void ListRepositories(out Dictionary<string, object> result)
362 {
363 Dictionary<string, object> res = new Dictionary<string, object>();
364 result = res;
365
366 AddinRepository[] reps = GetSortedAddinRepo();
367 if (reps.Length == 0)
368 {
369 MainConsole.Instance.Output("No repositories have been registered.");
370 return;
371 }
372
373 int count = 0;
374 foreach (AddinRepository rep in reps)
375 {
376 Dictionary<string, object> r = new Dictionary<string, object>();
377 r["enabled"] = rep.Enabled == true ? true : false;
378 r["name"] = rep.Name;
379 r["url"] = rep.Url;
380
381 res.Add(count.ToString(), r);
382 count++;
383 }
384 return;
385 }
386
387 /// <summary>
388 /// Updates the registry.
389 /// </summary>
390 public void UpdateRegistry()
391 {
392 PluginRegistry.Update();
393 }
394
395 // Show plugin info
396 /// <summary>
397 /// Addins the info.
398 /// </summary>
399 /// <returns>
400 /// The info.
401 /// </returns>
402 /// <param name='args'>
403 /// Arguments.
404 /// </param>
405 public bool AddinInfo(int ndx, out Dictionary<string, object> result)
406 {
407 Dictionary<string, object> res = new Dictionary<string, object>();
408 result = res;
409
410 Addin[] addins = GetSortedAddinList("RobustPlugin");
411
412 if (ndx > (addins.Length - 1))
413 {
414 MainConsole.Instance.Output("Selection out of range");
415 return false;
416 }
417 // author category description
418 Addin addin = addins[ndx];
419
420 res["author"] = addin.Description.Author;
421 res["category"] = addin.Description.Category;
422 res["description"] = addin.Description.Description;
423 res["name"] = addin.Name;
424 res["url"] = addin.Description.Url;
425 res["file_name"] = addin.Description.FileName;
426
427 result = res;
428 return true;
429 }
430
431 // Disable a plugin
432 /// <summary>
433 /// Disables the plugin.
434 /// </summary>
435 /// <param name='args'>
436 /// Arguments.
437 /// </param>
438 public void DisablePlugin(string[] args)
439 {
440 Addin[] addins = GetSortedAddinList("RobustPlugin");
441
442 int n = Convert.ToInt16(args[2]);
443 if (n > (addins.Length -1))
444 {
445 MainConsole.Instance.Output("Selection out of range");
446 return;
447 }
448
449 Addin addin = addins[n];
450 AddinManager.Registry.DisableAddin(addin.Id);
451 addin.Enabled = false;
452 return;
453 }
454
455 // Enable plugin
456 /// <summary>
457 /// Enables the plugin.
458 /// </summary>
459 /// <param name='args'>
460 /// Arguments.
461 /// </param>
462 public void EnablePlugin(string[] args)
463 {
464 Addin[] addins = GetSortedAddinList("RobustPlugin");
465
466 int n = Convert.ToInt16(args[2]);
467 if (n > (addins.Length -1))
468 {
469 MainConsole.Instance.Output("Selection out of range");
470 return;
471 }
472
473 Addin addin = addins[n];
474
475 addin.Enabled = true;
476 AddinManager.Registry.EnableAddin(addin.Id);
477 // AddinManager.Registry.Update();
478 if(PluginRegistry.IsAddinEnabled(addin.Id))
479 {
480 ConsoleProgressStatus ps = new ConsoleProgressStatus(false);
481 if (!AddinManager.AddinEngine.IsAddinLoaded(addin.Id))
482 {
483 MainConsole.Instance.Output("Ignore the following error...");
484 AddinManager.Registry.Rebuild(ps);
485 AddinManager.AddinEngine.LoadAddin(ps, addin.Id);
486 }
487 }
488 else
489 {
490 MainConsole.Instance.OutputFormat("Not Enabled in this domain {0}", addin.Name);
491 }
492 return;
493 }
494
495
496
497 #region Util
498 private void Testing()
499 {
500 Addin[] list = Registry.GetAddins();
501
502 var addins = list.Where( a => a.Description.Category == "RobustPlugin");
503
504 foreach (Addin addin in addins)
505 {
506 MainConsole.Instance.OutputFormat("Addin {0}", addin.Name);
507 }
508 }
509
510 // These will let us deal with numbered lists instead
511 // of needing to type in the full ids
512 private AddinRepositoryEntry[] GetSortedAvailbleAddins()
513 {
514 ArrayList list = new ArrayList();
515 list.AddRange(Repositories.GetAvailableAddins());
516
517 AddinRepositoryEntry[] addins = list.ToArray(typeof(AddinRepositoryEntry)) as AddinRepositoryEntry[];
518
519 Array.Sort(addins,(r1,r2) => r1.Addin.Id.CompareTo(r2.Addin.Id));
520
521 return addins;
522 }
523
524 private AddinRepository[] GetSortedAddinRepo()
525 {
526 ArrayList list = new ArrayList();
527 list.AddRange(Repositories.GetRepositories());
528
529 AddinRepository[] repos = list.ToArray(typeof(AddinRepository)) as AddinRepository[];
530 Array.Sort (repos,(r1,r2) => r1.Name.CompareTo(r2.Name));
531
532 return repos;
533 }
534
535 private Addin[] GetSortedAddinList(string category)
536 {
537
538 ArrayList xlist = new ArrayList();
539 ArrayList list = new ArrayList();
540 try
541 {
542 list.AddRange(PluginRegistry.GetAddins());
543 }
544 catch(Exception e)
545 {
546 Addin[] x = xlist.ToArray(typeof(Addin)) as Addin[];
547 return x;
548 }
549
550 foreach (Addin addin in list)
551 {
552 if (addin.Description.Category == category)
553 xlist.Add(addin);
554 }
555
556 Addin[] addins = xlist.ToArray(typeof(Addin)) as Addin[];
557 Array.Sort(addins,(r1,r2) => r1.Id.CompareTo(r2.Id));
558
559 return addins;
560 }
561 #endregion Util
562 }
563}
diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs
index fcc9873..948c259 100644
--- a/OpenSim/Framework/PrimitiveBaseShape.cs
+++ b/OpenSim/Framework/PrimitiveBaseShape.cs
@@ -192,18 +192,7 @@ namespace OpenSim.Framework
192 192
193 public PrimitiveBaseShape() 193 public PrimitiveBaseShape()
194 { 194 {
195 PCode = (byte) PCodeEnum.Primitive;
196 ExtraParams = new byte[1];
197 m_textureEntry = DEFAULT_TEXTURE;
198 }
199
200 public PrimitiveBaseShape(bool noShape)
201 {
202 if (noShape)
203 return;
204
205 PCode = (byte)PCodeEnum.Primitive; 195 PCode = (byte)PCodeEnum.Primitive;
206 ExtraParams = new byte[1];
207 m_textureEntry = DEFAULT_TEXTURE; 196 m_textureEntry = DEFAULT_TEXTURE;
208 } 197 }
209 198
@@ -216,7 +205,6 @@ namespace OpenSim.Framework
216// m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: Creating from {0}", prim.ID); 205// m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: Creating from {0}", prim.ID);
217 206
218 PCode = (byte)prim.PrimData.PCode; 207 PCode = (byte)prim.PrimData.PCode;
219 ExtraParams = new byte[1];
220 208
221 State = prim.PrimData.State; 209 State = prim.PrimData.State;
222 PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin); 210 PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin);
@@ -248,7 +236,10 @@ namespace OpenSim.Framework
248 SculptTexture = prim.Sculpt.SculptTexture; 236 SculptTexture = prim.Sculpt.SculptTexture;
249 SculptType = (byte)prim.Sculpt.Type; 237 SculptType = (byte)prim.Sculpt.Type;
250 } 238 }
251 else SculptType = (byte)OpenMetaverse.SculptType.None; 239 else
240 {
241 SculptType = (byte)OpenMetaverse.SculptType.None;
242 }
252 } 243 }
253 244
254 [XmlIgnore] 245 [XmlIgnore]
@@ -340,9 +331,9 @@ namespace OpenSim.Framework
340 _scale = new Vector3(side, side, side); 331 _scale = new Vector3(side, side, side);
341 } 332 }
342 333
343 public void SetHeigth(float heigth) 334 public void SetHeigth(float height)
344 { 335 {
345 _scale.Z = heigth; 336 _scale.Z = height;
346 } 337 }
347 338
348 public void SetRadius(float radius) 339 public void SetRadius(float radius)
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index e7bed6a..6dde62f 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -145,6 +145,7 @@ namespace OpenSim.Framework
145 public UUID RegionID = UUID.Zero; 145 public UUID RegionID = UUID.Zero;
146 public string RemotingAddress; 146 public string RemotingAddress;
147 public UUID ScopeID = UUID.Zero; 147 public UUID ScopeID = UUID.Zero;
148 private UUID m_maptileStaticUUID = UUID.Zero;
148 149
149 private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>(); 150 private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>();
150 151
@@ -340,6 +341,11 @@ namespace OpenSim.Framework
340 get { return m_regionType; } 341 get { return m_regionType; }
341 } 342 }
342 343
344 public UUID MaptileStaticUUID
345 {
346 get { return m_maptileStaticUUID; }
347 }
348
343 /// <summary> 349 /// <summary>
344 /// The port by which http communication occurs with the region (most noticeably, CAPS communication) 350 /// The port by which http communication occurs with the region (most noticeably, CAPS communication)
345 /// </summary> 351 /// </summary>
@@ -643,7 +649,7 @@ namespace OpenSim.Framework
643 m_regionType = config.GetString("RegionType", String.Empty); 649 m_regionType = config.GetString("RegionType", String.Empty);
644 allKeys.Remove("RegionType"); 650 allKeys.Remove("RegionType");
645 651
646 #region Prim stuff 652 #region Prim and map stuff
647 653
648 m_nonphysPrimMin = config.GetFloat("NonPhysicalPrimMin", 0); 654 m_nonphysPrimMin = config.GetFloat("NonPhysicalPrimMin", 0);
649 allKeys.Remove("NonPhysicalPrimMin"); 655 allKeys.Remove("NonPhysicalPrimMin");
@@ -665,6 +671,13 @@ namespace OpenSim.Framework
665 671
666 m_linksetCapacity = config.GetInt("LinksetPrims", 0); 672 m_linksetCapacity = config.GetInt("LinksetPrims", 0);
667 allKeys.Remove("LinksetPrims"); 673 allKeys.Remove("LinksetPrims");
674
675 allKeys.Remove("MaptileStaticUUID");
676 string mapTileStaticUUID = config.GetString("MaptileStaticUUID", UUID.Zero.ToString());
677 if (UUID.TryParse(mapTileStaticUUID.Trim(), out m_maptileStaticUUID))
678 {
679 config.Set("MaptileStaticUUID", m_maptileStaticUUID.ToString());
680 }
668 681
669 #endregion 682 #endregion
670 683
@@ -734,6 +747,9 @@ namespace OpenSim.Framework
734 747
735 if (RegionType != String.Empty) 748 if (RegionType != String.Empty)
736 config.Set("RegionType", RegionType); 749 config.Set("RegionType", RegionType);
750
751 if (m_maptileStaticUUID != UUID.Zero)
752 config.Set("MaptileStaticUUID", m_maptileStaticUUID.ToString());
737 } 753 }
738 754
739 public bool ignoreIncomingConfiguration(string configuration_key, object configuration_result) 755 public bool ignoreIncomingConfiguration(string configuration_key, object configuration_result)
@@ -832,6 +848,9 @@ namespace OpenSim.Framework
832 848
833 configMember.addConfigurationOption("region_type", ConfigurationOption.ConfigurationTypes.TYPE_STRING, 849 configMember.addConfigurationOption("region_type", ConfigurationOption.ConfigurationTypes.TYPE_STRING,
834 "Free form string describing the type of region", String.Empty, true); 850 "Free form string describing the type of region", String.Empty, true);
851
852 configMember.addConfigurationOption("region_static_maptile", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
853 "UUID of a texture to use as the map for this region", m_maptileStaticUUID.ToString(), true);
835 } 854 }
836 855
837 public void loadConfigurationOptions() 856 public void loadConfigurationOptions()
@@ -885,6 +904,9 @@ namespace OpenSim.Framework
885 904
886 configMember.addConfigurationOption("region_type", ConfigurationOption.ConfigurationTypes.TYPE_STRING, 905 configMember.addConfigurationOption("region_type", ConfigurationOption.ConfigurationTypes.TYPE_STRING,
887 "Region Type", String.Empty, true); 906 "Region Type", String.Empty, true);
907
908 configMember.addConfigurationOption("region_static_maptile", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
909 "UUID of a texture to use as the map for this region", String.Empty, true);
888 } 910 }
889 911
890 public bool handleIncomingConfiguration(string configuration_key, object configuration_result) 912 public bool handleIncomingConfiguration(string configuration_key, object configuration_result)
@@ -957,6 +979,9 @@ namespace OpenSim.Framework
957 case "region_type": 979 case "region_type":
958 m_regionType = (string)configuration_result; 980 m_regionType = (string)configuration_result;
959 break; 981 break;
982 case "region_static_maptile":
983 m_maptileStaticUUID = (UUID)configuration_result;
984 break;
960 } 985 }
961 986
962 return true; 987 return true;
diff --git a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
index d670f2f..f836350 100644
--- a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
index 7309a12..72fa679 100644
--- a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs
index 48f1c4f..0c12787 100644
--- a/OpenSim/Framework/Serialization/ArchiveConstants.cs
+++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs
@@ -154,6 +154,11 @@ namespace OpenSim.Framework.Serialization
154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder; 154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder;
155 } 155 }
156 156
157 public static string CreateOarLandDataPath(LandData ld)
158 {
159 return string.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, ld.GlobalID);
160 }
161
157 /// <summary> 162 /// <summary>
158 /// Create the filename used to store an object in an OpenSim Archive. 163 /// Create the filename used to store an object in an OpenSim Archive.
159 /// </summary> 164 /// </summary>
diff --git a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
index 11efa4b..7a122da 100644
--- a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
index 8b9756b..ea100ee 100644
--- a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
+++ b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
@@ -37,7 +37,7 @@ using OpenSim.Tests.Common;
37namespace OpenSim.Framework.Serialization.Tests 37namespace OpenSim.Framework.Serialization.Tests
38{ 38{
39 [TestFixture] 39 [TestFixture]
40 public class LandDataSerializerTest 40 public class LandDataSerializerTest : OpenSimTestCase
41 { 41 {
42 private LandData land; 42 private LandData land;
43 private LandData landWithParcelAccessList; 43 private LandData landWithParcelAccessList;
diff --git a/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs
index 09b6f6d..142726b 100644
--- a/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs
+++ b/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs
@@ -37,7 +37,7 @@ using OpenSim.Tests.Common;
37namespace OpenSim.Framework.Serialization.Tests 37namespace OpenSim.Framework.Serialization.Tests
38{ 38{
39 [TestFixture] 39 [TestFixture]
40 public class RegionSettingsSerializerTests 40 public class RegionSettingsSerializerTests : OpenSimTestCase
41 { 41 {
42 private string m_serializedRs = @"<?xml version=""1.0"" encoding=""utf-16""?> 42 private string m_serializedRs = @"<?xml version=""1.0"" encoding=""utf-16""?>
43<RegionSettings> 43<RegionSettings>
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 2c21800..cb47cbf 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -27,7 +27,6 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
31using System.IO; 30using System.IO;
32using System.Reflection; 31using System.Reflection;
33using System.Text; 32using System.Text;
@@ -99,34 +98,6 @@ namespace OpenSim.Framework.Servers
99 m_console.Commands.AddCommand("General", false, "shutdown", 98 m_console.Commands.AddCommand("General", false, "shutdown",
100 "shutdown", 99 "shutdown",
101 "Quit the application", HandleQuit); 100 "Quit the application", HandleQuit);
102
103 m_console.Commands.AddCommand("General", false, "show threads",
104 "show threads",
105 "Show thread status", HandleShow);
106
107 m_console.Commands.AddCommand("General", false, "show version",
108 "show version",
109 "Show server version", HandleShow);
110
111 m_console.Commands.AddCommand("General", false, "threads abort",
112 "threads abort <thread-id>",
113 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
114
115 m_console.Commands.AddCommand("General", false, "threads show",
116 "threads show",
117 "Show thread status. Synonym for \"show threads\"",
118 (string module, string[] args) => Notice(GetThreadsReport()));
119
120 m_console.Commands.AddCommand("General", false, "force gc",
121 "force gc",
122 "Manually invoke runtime garbage collection. For debugging purposes",
123 HandleForceGc);
124 }
125
126 private void HandleForceGc(string module, string[] args)
127 {
128 MainConsole.Instance.Output("Manually invoking runtime garbage collection");
129 GC.Collect();
130 } 101 }
131 102
132 /// <summary> 103 /// <summary>
@@ -159,54 +130,6 @@ namespace OpenSim.Framework.Servers
159 } 130 }
160 131
161 /// <summary> 132 /// <summary>
162 /// Get a report about the registered threads in this server.
163 /// </summary>
164 protected string GetThreadsReport()
165 {
166 // This should be a constant field.
167 string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
168
169 StringBuilder sb = new StringBuilder();
170 Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
171
172 sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
173
174 int timeNow = Environment.TickCount & Int32.MaxValue;
175
176 sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE");
177 sb.Append(Environment.NewLine);
178
179 foreach (Watchdog.ThreadWatchdogInfo twi in threads)
180 {
181 Thread t = twi.Thread;
182
183 sb.AppendFormat(
184 reportFormat,
185 t.ManagedThreadId,
186 t.Name,
187 timeNow - twi.LastTick,
188 timeNow - twi.FirstTick,
189 t.Priority,
190 t.ThreadState);
191
192 sb.Append("\n");
193 }
194
195 sb.Append("\n");
196
197 // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
198 // zero active threads.
199 int totalThreads = Process.GetCurrentProcess().Threads.Count;
200 if (totalThreads > 0)
201 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
202
203 sb.Append("Main threadpool (excluding script engine pools)\n");
204 sb.Append(Util.GetThreadPoolReport());
205
206 return sb.ToString();
207 }
208
209 /// <summary>
210 /// Performs initialisation of the scene, such as loading configuration from disk. 133 /// Performs initialisation of the scene, such as loading configuration from disk.
211 /// </summary> 134 /// </summary>
212 public virtual void Startup() 135 public virtual void Startup()
@@ -246,50 +169,7 @@ namespace OpenSim.Framework.Servers
246 private void HandleQuit(string module, string[] args) 169 private void HandleQuit(string module, string[] args)
247 { 170 {
248 Shutdown(); 171 Shutdown();
249 } 172 }
250
251 public override void HandleShow(string module, string[] cmd)
252 {
253 base.HandleShow(module, cmd);
254
255 List<string> args = new List<string>(cmd);
256
257 args.RemoveAt(0);
258
259 string[] showParams = args.ToArray();
260
261 switch (showParams[0])
262 {
263 case "threads":
264 Notice(GetThreadsReport());
265 break;
266
267 case "version":
268 Notice(GetVersionText());
269 break;
270 }
271 }
272
273 public virtual void HandleThreadsAbort(string module, string[] cmd)
274 {
275 if (cmd.Length != 3)
276 {
277 MainConsole.Instance.Output("Usage: threads abort <thread-id>");
278 return;
279 }
280
281 int threadId;
282 if (!int.TryParse(cmd[2], out threadId))
283 {
284 MainConsole.Instance.Output("ERROR: Thread id must be an integer");
285 return;
286 }
287
288 if (Watchdog.AbortThread(threadId))
289 MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
290 else
291 MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
292 }
293 173
294 public string osSecret { 174 public string osSecret {
295 // Secret uuid for the simulator 175 // Secret uuid for the simulator
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 77fce9e..27af009 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,6 +54,16 @@ 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
58 /// <summary>
59 /// This is a pending websocket request before it got an sucessful upgrade response.
60 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
61 /// start the connection and optionally provide an origin authentication method.
62 /// </summary>
63 /// <param name="servicepath"></param>
64 /// <param name="handler"></param>
65 public delegate void WebSocketRequestDelegate(string servicepath, WebSocketHttpServerHandler handler);
66
57 /// <summary> 67 /// <summary>
58 /// Gets or sets the debug level. 68 /// Gets or sets the debug level.
59 /// </summary> 69 /// </summary>
@@ -77,6 +87,7 @@ namespace OpenSim.Framework.Servers.HttpServer
77 // protected HttpListener m_httpListener; 87 // protected HttpListener m_httpListener;
78 protected CoolHTTPListener m_httpListener2; 88 protected CoolHTTPListener m_httpListener2;
79 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>(); 89 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>();
90 protected Dictionary<string, JsonRPCMethod> jsonRpcHandlers = new Dictionary<string, JsonRPCMethod>();
80 protected Dictionary<string, bool> m_rpcHandlersKeepAlive = new Dictionary<string, bool>(); 91 protected Dictionary<string, bool> m_rpcHandlersKeepAlive = new Dictionary<string, bool>();
81 protected DefaultLLSDMethod m_defaultLlsdHandler = null; // <-- Moving away from the monolithic.. and going to /registered/ 92 protected DefaultLLSDMethod m_defaultLlsdHandler = null; // <-- Moving away from the monolithic.. and going to /registered/
82 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>(); 93 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>();
@@ -86,6 +97,9 @@ namespace OpenSim.Framework.Servers.HttpServer
86 protected Dictionary<string, PollServiceEventArgs> m_pollHandlers = 97 protected Dictionary<string, PollServiceEventArgs> m_pollHandlers =
87 new Dictionary<string, PollServiceEventArgs>(); 98 new Dictionary<string, PollServiceEventArgs>();
88 99
100 protected Dictionary<string, WebSocketRequestDelegate> m_WebSocketHandlers =
101 new Dictionary<string, WebSocketRequestDelegate>();
102
89 protected uint m_port; 103 protected uint m_port;
90 protected uint m_sslport; 104 protected uint m_sslport;
91 protected bool m_ssl; 105 protected bool m_ssl;
@@ -169,6 +183,22 @@ namespace OpenSim.Framework.Servers.HttpServer
169 } 183 }
170 } 184 }
171 185
186 public void AddWebSocketHandler(string servicepath, WebSocketRequestDelegate handler)
187 {
188 lock (m_WebSocketHandlers)
189 {
190 if (!m_WebSocketHandlers.ContainsKey(servicepath))
191 m_WebSocketHandlers.Add(servicepath, handler);
192 }
193 }
194
195 public void RemoveWebSocketHandler(string servicepath)
196 {
197 lock (m_WebSocketHandlers)
198 if (m_WebSocketHandlers.ContainsKey(servicepath))
199 m_WebSocketHandlers.Remove(servicepath);
200 }
201
172 public List<string> GetStreamHandlerKeys() 202 public List<string> GetStreamHandlerKeys()
173 { 203 {
174 lock (m_streamHandlers) 204 lock (m_streamHandlers)
@@ -217,6 +247,37 @@ namespace OpenSim.Framework.Servers.HttpServer
217 return new List<string>(m_rpcHandlers.Keys); 247 return new List<string>(m_rpcHandlers.Keys);
218 } 248 }
219 249
250 // JsonRPC
251 public bool AddJsonRPCHandler(string method, JsonRPCMethod handler)
252 {
253 lock(jsonRpcHandlers)
254 {
255 jsonRpcHandlers.Add(method, handler);
256 }
257 return true;
258 }
259
260 public JsonRPCMethod GetJsonRPCHandler(string method)
261 {
262 lock (jsonRpcHandlers)
263 {
264 if (jsonRpcHandlers.ContainsKey(method))
265 {
266 return jsonRpcHandlers[method];
267 }
268 else
269 {
270 return null;
271 }
272 }
273 }
274
275 public List<string> GetJsonRpcHandlerKeys()
276 {
277 lock (jsonRpcHandlers)
278 return new List<string>(jsonRpcHandlers.Keys);
279 }
280
220 public bool AddHTTPHandler(string methodName, GenericHTTPMethod handler) 281 public bool AddHTTPHandler(string methodName, GenericHTTPMethod handler)
221 { 282 {
222 //m_log.DebugFormat("[BASE HTTP SERVER]: Registering {0}", methodName); 283 //m_log.DebugFormat("[BASE HTTP SERVER]: Registering {0}", methodName);
@@ -378,9 +439,24 @@ namespace OpenSim.Framework.Servers.HttpServer
378 439
379 public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) 440 public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
380 { 441 {
442
381 OSHttpRequest req = new OSHttpRequest(context, request); 443 OSHttpRequest req = new OSHttpRequest(context, request);
444 WebSocketRequestDelegate dWebSocketRequestDelegate = null;
445 lock (m_WebSocketHandlers)
446 {
447 if (m_WebSocketHandlers.ContainsKey(req.RawUrl))
448 dWebSocketRequestDelegate = m_WebSocketHandlers[req.RawUrl];
449 }
450 if (dWebSocketRequestDelegate != null)
451 {
452 dWebSocketRequestDelegate(req.Url.AbsolutePath, new WebSocketHttpServerHandler(req, context, 8192));
453 return;
454 }
455
382 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 456 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
457
383 HandleRequest(req, resp); 458 HandleRequest(req, resp);
459
384 460
385 // !!!HACK ALERT!!! 461 // !!!HACK ALERT!!!
386 // There seems to be a bug in the underlying http code that makes subsequent requests 462 // There seems to be a bug in the underlying http code that makes subsequent requests
@@ -437,7 +513,7 @@ namespace OpenSim.Framework.Servers.HttpServer
437// reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); 513// reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]);
438 //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); 514 //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl);
439 515
440 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); 516 Culture.SetCurrentCulture();
441 517
442// // This is the REST agent interface. We require an agent to properly identify 518// // This is the REST agent interface. We require an agent to properly identify
443// // itself. If the REST handler recognizes the prefix it will attempt to 519// // itself. If the REST handler recognizes the prefix it will attempt to
@@ -469,7 +545,7 @@ namespace OpenSim.Framework.Servers.HttpServer
469 LogIncomingToStreamHandler(request, requestHandler); 545 LogIncomingToStreamHandler(request, requestHandler);
470 546
471 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. 547 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
472 548
473 if (requestHandler is IStreamedRequestHandler) 549 if (requestHandler is IStreamedRequestHandler)
474 { 550 {
475 IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler; 551 IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler;
@@ -557,10 +633,18 @@ namespace OpenSim.Framework.Servers.HttpServer
557 633
558 buffer = HandleLLSDRequests(request, response); 634 buffer = HandleLLSDRequests(request, response);
559 break; 635 break;
636
637 case "application/json-rpc":
638 if (DebugLevel >= 3)
639 LogIncomingToContentTypeHandler(request);
640
641 buffer = HandleJsonRpcRequests(request, response);
642 break;
560 643
561 case "text/xml": 644 case "text/xml":
562 case "application/xml": 645 case "application/xml":
563 case "application/json": 646 case "application/json":
647
564 default: 648 default:
565 //m_log.Info("[Debug BASE HTTP SERVER]: in default handler"); 649 //m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
566 // Point of note.. the DoWeHaveA methods check for an EXACT path 650 // Point of note.. the DoWeHaveA methods check for an EXACT path
@@ -986,6 +1070,93 @@ namespace OpenSim.Framework.Servers.HttpServer
986 return buffer; 1070 return buffer;
987 } 1071 }
988 1072
1073 // JsonRpc (v2.0 only)
1074 // Batch requests not yet supported
1075 private byte[] HandleJsonRpcRequests(OSHttpRequest request, OSHttpResponse response)
1076 {
1077 Stream requestStream = request.InputStream;
1078 JsonRpcResponse jsonRpcResponse = new JsonRpcResponse();
1079 OSDMap jsonRpcRequest = null;
1080
1081 try
1082 {
1083 jsonRpcRequest = (OSDMap)OSDParser.DeserializeJson(requestStream);
1084 }
1085 catch (LitJson.JsonException e)
1086 {
1087 jsonRpcResponse.Error.Code = ErrorCode.InternalError;
1088 jsonRpcResponse.Error.Message = e.Message;
1089 }
1090
1091 requestStream.Close();
1092
1093 if (jsonRpcRequest != null)
1094 {
1095 if (jsonRpcRequest.ContainsKey("jsonrpc") || jsonRpcRequest["jsonrpc"].AsString() == "2.0")
1096 {
1097 jsonRpcResponse.JsonRpc = "2.0";
1098
1099 // If we have no id, then it's a "notification"
1100 if (jsonRpcRequest.ContainsKey("id"))
1101 {
1102 jsonRpcResponse.Id = jsonRpcRequest["id"].AsString();
1103 }
1104
1105 string methodname = jsonRpcRequest["method"];
1106 JsonRPCMethod method;
1107
1108 if (jsonRpcHandlers.ContainsKey(methodname))
1109 {
1110 lock(jsonRpcHandlers)
1111 {
1112 jsonRpcHandlers.TryGetValue(methodname, out method);
1113 }
1114 bool res = false;
1115 try
1116 {
1117 res = method(jsonRpcRequest, ref jsonRpcResponse);
1118 if(!res)
1119 {
1120 // The handler sent back an unspecified error
1121 if(jsonRpcResponse.Error.Code == 0)
1122 {
1123 jsonRpcResponse.Error.Code = ErrorCode.InternalError;
1124 }
1125 }
1126 }
1127 catch (Exception e)
1128 {
1129 string ErrorMessage = string.Format("[BASE HTTP SERVER]: Json-Rpc Handler Error method {0} - {1}", methodname, e.Message);
1130 m_log.Error(ErrorMessage);
1131 jsonRpcResponse.Error.Code = ErrorCode.InternalError;
1132 jsonRpcResponse.Error.Message = ErrorMessage;
1133 }
1134 }
1135 else // Error no hanlder defined for requested method
1136 {
1137 jsonRpcResponse.Error.Code = ErrorCode.InvalidRequest;
1138 jsonRpcResponse.Error.Message = string.Format ("No handler defined for {0}", methodname);
1139 }
1140 }
1141 else // not json-rpc 2.0 could be v1
1142 {
1143 jsonRpcResponse.Error.Code = ErrorCode.InvalidRequest;
1144 jsonRpcResponse.Error.Message = "Must be valid json-rpc 2.0 see: http://www.jsonrpc.org/specification";
1145
1146 if (jsonRpcRequest.ContainsKey("id"))
1147 jsonRpcResponse.Id = jsonRpcRequest["id"].AsString();
1148 }
1149 }
1150
1151 response.KeepAlive = true;
1152 string responseData = string.Empty;
1153
1154 responseData = jsonRpcResponse.Serialize();
1155
1156 byte[] buffer = Encoding.UTF8.GetBytes(responseData);
1157 return buffer;
1158 }
1159
989 private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response) 1160 private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
990 { 1161 {
991 //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request"); 1162 //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request");
@@ -1283,59 +1454,6 @@ namespace OpenSim.Framework.Servers.HttpServer
1283 map["login"] = OSD.FromString("false"); 1454 map["login"] = OSD.FromString("false");
1284 return map; 1455 return map;
1285 } 1456 }
1286 /// <summary>
1287 /// A specific agent handler was provided. Such a handler is expecetd to have an
1288 /// intimate, and highly specific relationship with the client. Consequently,
1289 /// nothing is done here.
1290 /// </summary>
1291 /// <param name="handler"></param>
1292 /// <param name="request"></param>
1293 /// <param name="response"></param>
1294
1295 private bool HandleAgentRequest(IHttpAgentHandler handler, OSHttpRequest request, OSHttpResponse response)
1296 {
1297 // In the case of REST, then handler is responsible for ALL aspects of
1298 // the request/response handling. Nothing is done here, not even encoding.
1299
1300 try
1301 {
1302 return handler.Handle(request, response);
1303 }
1304 catch (Exception e)
1305 {
1306 // If the handler did in fact close the stream, then this will blow
1307 // chunks. So that that doesn't disturb anybody we throw away any
1308 // and all exceptions raised. We've done our best to release the
1309 // client.
1310 try
1311 {
1312 m_log.Warn("[HTTP-AGENT]: Error - " + e.Message);
1313 response.SendChunked = false;
1314 response.KeepAlive = true;
1315 response.StatusCode = (int)OSHttpStatusCode.ServerErrorInternalError;
1316 //response.OutputStream.Close();
1317 try
1318 {
1319 response.Send();
1320 //response.FreeContext();
1321 }
1322 catch (SocketException f)
1323 {
1324 // This has to be here to prevent a Linux/Mono crash
1325 m_log.Warn(
1326 String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", f.Message), f);
1327 }
1328 }
1329 catch(Exception)
1330 {
1331 }
1332 }
1333
1334 // Indicate that the request has been "handled"
1335
1336 return true;
1337
1338 }
1339 1457
1340 public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response) 1458 public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
1341 { 1459 {
@@ -1775,6 +1893,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1775 HTTPDRunning = false; 1893 HTTPDRunning = false;
1776 try 1894 try
1777 { 1895 {
1896// m_PollServiceManager.Stop();
1897
1778 m_httpListener2.ExceptionThrown -= httpServerException; 1898 m_httpListener2.ExceptionThrown -= httpServerException;
1779 //m_httpListener2.DisconnectHandler = null; 1899 //m_httpListener2.DisconnectHandler = null;
1780 1900
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
index 0bd3aae..71ca3ff 100644
--- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
@@ -97,6 +97,18 @@ namespace OpenSim.Framework.Servers.HttpServer
97 bool AddXmlRPCHandler(string method, XmlRpcMethod handler); 97 bool AddXmlRPCHandler(string method, XmlRpcMethod handler);
98 bool AddXmlRPCHandler(string method, XmlRpcMethod handler, bool keepAlive); 98 bool AddXmlRPCHandler(string method, XmlRpcMethod handler, bool keepAlive);
99 99
100 bool AddJsonRPCHandler(string method, JsonRPCMethod handler);
101
102 /// <summary>
103 /// Websocket HTTP server handlers.
104 /// </summary>
105 /// <param name="servicepath"></param>
106 /// <param name="handler"></param>
107 void AddWebSocketHandler(string servicepath, BaseHttpServer.WebSocketRequestDelegate handler);
108
109
110 void RemoveWebSocketHandler(string servicepath);
111
100 /// <summary> 112 /// <summary>
101 /// Gets the XML RPC handler for given method name 113 /// Gets the XML RPC handler for given method name
102 /// </summary> 114 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/Scripting/ScriptEngineInterface.cs b/OpenSim/Framework/Servers/HttpServer/JsonRPCMethod.cs
index 812a21c..5bab508 100644
--- a/OpenSim/Region/Framework/Scenes/Scripting/ScriptEngineInterface.cs
+++ b/OpenSim/Framework/Servers/HttpServer/JsonRPCMethod.cs
@@ -25,14 +25,10 @@
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//TODO: WHERE TO PLACE THIS? 28using System.Net;
29using OpenMetaverse.StructuredData;
29 30
30namespace OpenSim.Region.Framework.Scenes.Scripting 31namespace OpenSim.Framework.Servers.HttpServer
31{ 32{
32 public interface ScriptEngineInterface 33 public delegate bool JsonRPCMethod(OSDMap jsonRpcRequest, ref JsonRpcResponse response);
33 {
34 void InitializeEngine(Scene Sceneworld);
35 void Shutdown();
36// void StartScript(string ScriptID, IScriptHost ObjectID);
37 }
38} 34}
diff --git a/OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs b/OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs
new file mode 100644
index 0000000..2c50587
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs
@@ -0,0 +1,150 @@
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 */
27using System;
28using System.Net;
29using OpenMetaverse.StructuredData;
30
31namespace OpenSim.Framework.Servers.HttpServer
32{
33 public sealed class ErrorCode
34 {
35 private ErrorCode() {}
36
37 public const int ParseError = -32700;
38 public const int InvalidRequest = -32600;
39 public const int MethodNotFound = -32601;
40 public const int InvalidParams = -32602;
41 public const int InternalError = -32604;
42
43 }
44
45 public class JsonRpcError
46 {
47 internal OSDMap Error = new OSDMap();
48
49 public int Code
50 {
51 get
52 {
53 if (Error.ContainsKey("code"))
54 return Error["code"].AsInteger();
55 else
56 return 0;
57 }
58 set
59 {
60 Error["code"] = OSD.FromInteger(value);
61 }
62 }
63
64 public string Message
65 {
66 get
67 {
68 if (Error.ContainsKey("message"))
69 return Error["message"].AsString();
70 else
71 return null;
72 }
73 set
74 {
75 Error["message"] = OSD.FromString(value);
76 }
77 }
78
79 public OSD Data
80 {
81 get; set;
82 }
83 }
84
85 public class JsonRpcResponse
86 {
87 public string JsonRpc
88 {
89 get
90 {
91 return Reply["jsonrpc"].AsString();
92 }
93 set
94 {
95 Reply["jsonrpc"] = OSD.FromString(value);
96 }
97 }
98
99 public string Id
100 {
101 get
102 {
103 return Reply["id"].AsString();
104 }
105 set
106 {
107 Reply["id"] = OSD.FromString(value);
108 }
109 }
110
111 public OSD Result
112 {
113 get; set;
114 }
115
116 public JsonRpcError Error
117 {
118 get; set;
119 }
120
121 public OSDMap Reply = new OSDMap();
122
123 public JsonRpcResponse()
124 {
125 Error = new JsonRpcError();
126 }
127
128 public string Serialize()
129 {
130 if (Result != null)
131 Reply["result"] = Result;
132
133 if (Error.Code != 0)
134 {
135 Reply["error"] = (OSD)Error.Error;
136 }
137
138 string result = string.Empty;
139 try
140 {
141 result = OSDParser.SerializeJsonString(Reply);
142 }
143 catch
144 {
145
146 }
147 return result;
148 }
149 }
150}
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 4be8bf4..07bd48a 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -50,19 +50,26 @@ namespace OpenSim.Framework.Servers.HttpServer
50 private uint m_WorkerThreadCount = 0; 50 private uint m_WorkerThreadCount = 0;
51 private Thread[] m_workerThreads; 51 private Thread[] m_workerThreads;
52 private PollServiceWorkerThread[] m_PollServiceWorkerThreads; 52 private PollServiceWorkerThread[] m_PollServiceWorkerThreads;
53 private bool m_running = true; 53 private volatile bool m_running = true;
54 private int m_pollTimeout;
54 55
55 public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout) 56 public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
56 { 57 {
57 m_server = pSrv; 58 m_server = pSrv;
58 m_WorkerThreadCount = pWorkerThreadCount; 59 m_WorkerThreadCount = pWorkerThreadCount;
60 m_pollTimeout = pTimeout;
61 }
62
63 public void Start()
64 {
65 m_running = true;
59 m_workerThreads = new Thread[m_WorkerThreadCount]; 66 m_workerThreads = new Thread[m_WorkerThreadCount];
60 m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount]; 67 m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount];
61 68
62 //startup worker threads 69 //startup worker threads
63 for (uint i = 0; i < m_WorkerThreadCount; i++) 70 for (uint i = 0; i < m_WorkerThreadCount; i++)
64 { 71 {
65 m_PollServiceWorkerThreads[i] = new PollServiceWorkerThread(m_server, pTimeout); 72 m_PollServiceWorkerThreads[i] = new PollServiceWorkerThread(m_server, m_pollTimeout);
66 m_PollServiceWorkerThreads[i].ReQueue += ReQueueEvent; 73 m_PollServiceWorkerThreads[i].ReQueue += ReQueueEvent;
67 74
68 m_workerThreads[i] 75 m_workerThreads[i]
@@ -141,8 +148,10 @@ namespace OpenSim.Framework.Servers.HttpServer
141 148
142 } 149 }
143 150
144 ~PollServiceRequestManager() 151 public void Stop()
145 { 152 {
153 m_running = false;
154
146 foreach (object o in m_requests) 155 foreach (object o in m_requests)
147 { 156 {
148 PollServiceHttpRequest req = (PollServiceHttpRequest) o; 157 PollServiceHttpRequest req = (PollServiceHttpRequest) o;
@@ -157,7 +166,6 @@ namespace OpenSim.Framework.Servers.HttpServer
157 { 166 {
158 t.Abort(); 167 t.Abort();
159 } 168 }
160 m_running = false;
161 } 169 }
162 } 170 }
163} 171}
diff --git a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
index 02ecc25..386be2d 100644
--- a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
new file mode 100644
index 0000000..cfb1605
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
@@ -0,0 +1,1085 @@
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.Security.Cryptography;
32using System.Text;
33using HttpServer;
34
35namespace OpenSim.Framework.Servers.HttpServer
36{
37 // Sealed class. If you're going to unseal it, implement IDisposable.
38 /// <summary>
39 /// This class implements websockets. It grabs the network context from C#Webserver and utilizes it directly as a tcp streaming service
40 /// </summary>
41 public sealed class WebSocketHttpServerHandler : BaseRequestHandler
42 {
43
44 private class WebSocketState
45 {
46 public List<byte> ReceivedBytes;
47 public int ExpectedBytes;
48 public WebsocketFrameHeader Header;
49 public bool FrameComplete;
50 public WebSocketFrame ContinuationFrame;
51 }
52
53 /// <summary>
54 /// Binary Data will trigger this event
55 /// </summary>
56 public event DataDelegate OnData;
57
58 /// <summary>
59 /// Textual Data will trigger this event
60 /// </summary>
61 public event TextDelegate OnText;
62
63 /// <summary>
64 /// A ping request form the other side will trigger this event.
65 /// This class responds to the ping automatically. You shouldn't send a pong.
66 /// it's informational.
67 /// </summary>
68 public event PingDelegate OnPing;
69
70 /// <summary>
71 /// This is a response to a ping you sent.
72 /// </summary>
73 public event PongDelegate OnPong;
74
75 /// <summary>
76 /// This is a regular HTTP Request... This may be removed in the future.
77 /// </summary>
78 public event RegularHttpRequestDelegate OnRegularHttpRequest;
79
80 /// <summary>
81 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
82 /// </summary>
83 public event UpgradeCompletedDelegate OnUpgradeCompleted;
84
85 /// <summary>
86 /// If the upgrade failed, this will be fired
87 /// </summary>
88 public event UpgradeFailedDelegate OnUpgradeFailed;
89
90 /// <summary>
91 /// When the websocket is closed, this will be fired.
92 /// </summary>
93 public event CloseDelegate OnClose;
94
95 /// <summary>
96 /// Set this delegate to allow your module to validate the origin of the
97 /// Websocket request. Primary line of defense against cross site scripting
98 /// </summary>
99 public ValidateHandshake HandshakeValidateMethodOverride = null;
100
101 private OSHttpRequest _request;
102 private HTTPNetworkContext _networkContext;
103 private IHttpClientContext _clientContext;
104
105 private int _pingtime = 0;
106 private byte[] _buffer;
107 private int _bufferPosition;
108 private int _bufferLength;
109 private bool _closing;
110 private bool _upgraded;
111
112 private const string HandshakeAcceptText =
113 "HTTP/1.1 101 Switching Protocols\r\n" +
114 "upgrade: websocket\r\n" +
115 "Connection: Upgrade\r\n" +
116 "sec-websocket-accept: {0}\r\n\r\n";// +
117 //"{1}";
118
119 private const string HandshakeDeclineText =
120 "HTTP/1.1 {0} {1}\r\n" +
121 "Connection: close\r\n\r\n";
122
123 /// <summary>
124 /// Mysterious constant defined in RFC6455 to append to the client provided security key
125 /// </summary>
126 private const string WebsocketHandshakeAcceptHashConstant = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
127
128 public WebSocketHttpServerHandler(OSHttpRequest preq, IHttpClientContext pContext, int bufferlen)
129 : base(preq.HttpMethod, preq.Url.OriginalString)
130 {
131 _request = preq;
132 _networkContext = pContext.GiveMeTheNetworkStreamIKnowWhatImDoing();
133 _clientContext = pContext;
134 _bufferLength = bufferlen;
135 _buffer = new byte[_bufferLength];
136 }
137
138 // Sealed class implments destructor and an internal dispose method. complies with C# unmanaged resource best practices.
139 ~WebSocketHttpServerHandler()
140 {
141 Dispose();
142
143 }
144
145 /// <summary>
146 /// Sets the length of the stream buffer
147 /// </summary>
148 /// <param name="pChunk">Byte length.</param>
149 public void SetChunksize(int pChunk)
150 {
151 if (!_upgraded)
152 {
153 _buffer = new byte[pChunk];
154 }
155 else
156 {
157 throw new InvalidOperationException("You must set the chunksize before the connection is upgraded");
158 }
159 }
160
161 /// <summary>
162 /// This is the famous nagle.
163 /// </summary>
164 public bool NoDelay_TCP_Nagle
165 {
166 get
167 {
168 if (_networkContext != null && _networkContext.Socket != null)
169 {
170 return _networkContext.Socket.NoDelay;
171 }
172 else
173 {
174 throw new InvalidOperationException("The socket has been shutdown");
175 }
176 }
177 set
178 {
179 if (_networkContext != null && _networkContext.Socket != null)
180 _networkContext.Socket.NoDelay = value;
181 else
182 {
183 throw new InvalidOperationException("The socket has been shutdown");
184 }
185 }
186 }
187
188 /// <summary>
189 /// This triggers the websocket to start the upgrade process...
190 /// This is a Generalized Networking 'common sense' helper method. Some people expect to call Start() instead
191 /// of the more context appropriate HandshakeAndUpgrade()
192 /// </summary>
193 public void Start()
194 {
195 HandshakeAndUpgrade();
196 }
197
198 /// <summary>
199 /// This triggers the websocket start the upgrade process
200 /// </summary>
201 public void HandshakeAndUpgrade()
202 {
203 string webOrigin = string.Empty;
204 string websocketKey = string.Empty;
205 string acceptKey = string.Empty;
206 string accepthost = string.Empty;
207 if (!string.IsNullOrEmpty(_request.Headers["origin"]))
208 webOrigin = _request.Headers["origin"];
209
210 if (!string.IsNullOrEmpty(_request.Headers["sec-websocket-key"]))
211 websocketKey = _request.Headers["sec-websocket-key"];
212
213 if (!string.IsNullOrEmpty(_request.Headers["host"]))
214 accepthost = _request.Headers["host"];
215
216 if (string.IsNullOrEmpty(_request.Headers["upgrade"]))
217 {
218 FailUpgrade(OSHttpStatusCode.ClientErrorBadRequest, "no upgrade request submitted");
219 }
220
221 string connectionheader = _request.Headers["upgrade"];
222 if (connectionheader.ToLower() != "websocket")
223 {
224 FailUpgrade(OSHttpStatusCode.ClientErrorBadRequest, "no connection upgrade request submitted");
225 }
226
227 // If the object consumer provided a method to validate the origin, we should call it and give the client a success or fail.
228 // If not.. we should accept any. The assumption here is that there would be no Websocket handlers registered in baseHTTPServer unless
229 // Something asked for it...
230 if (HandshakeValidateMethodOverride != null)
231 {
232 if (HandshakeValidateMethodOverride(webOrigin, websocketKey, accepthost))
233 {
234 acceptKey = GenerateAcceptKey(websocketKey);
235 string rawaccept = string.Format(HandshakeAcceptText, acceptKey);
236 SendUpgradeSuccess(rawaccept);
237
238 }
239 else
240 {
241 FailUpgrade(OSHttpStatusCode.ClientErrorForbidden, "Origin Validation Failed");
242 }
243 }
244 else
245 {
246 acceptKey = GenerateAcceptKey(websocketKey);
247 string rawaccept = string.Format(HandshakeAcceptText, acceptKey);
248 SendUpgradeSuccess(rawaccept);
249 }
250 }
251
252 /// <summary>
253 /// Generates a handshake response key string based on the client's
254 /// provided key to prove to the client that we're allowing the Websocket
255 /// upgrade of our own free will and we were not coerced into doing it.
256 /// </summary>
257 /// <param name="key">Client provided security key</param>
258 /// <returns></returns>
259 private static string GenerateAcceptKey(string key)
260 {
261 if (string.IsNullOrEmpty(key))
262 return string.Empty;
263
264 string acceptkey = key + WebsocketHandshakeAcceptHashConstant;
265
266 SHA1 hashobj = SHA1.Create();
267 string ret = Convert.ToBase64String(hashobj.ComputeHash(Encoding.UTF8.GetBytes(acceptkey)));
268 hashobj.Clear();
269
270 return ret;
271 }
272
273 /// <summary>
274 /// Informs the otherside that we accepted their upgrade request
275 /// </summary>
276 /// <param name="pHandshakeResponse">The HTTP 1.1 101 response that says Yay \o/ </param>
277 private void SendUpgradeSuccess(string pHandshakeResponse)
278 {
279 // Create a new websocket state so we can keep track of data in between network reads.
280 WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List<byte>(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true};
281
282 byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse);
283 try
284 {
285
286 // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream.
287 _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState);
288
289 // Write the upgrade handshake success message
290 _networkContext.Stream.Write(bhandshakeResponse, 0, bhandshakeResponse.Length);
291 _networkContext.Stream.Flush();
292 _upgraded = true;
293 UpgradeCompletedDelegate d = OnUpgradeCompleted;
294 if (d != null)
295 d(this, new UpgradeCompletedEventArgs());
296 }
297 catch (IOException fail)
298 {
299 Close(string.Empty);
300 }
301 catch (ObjectDisposedException fail)
302 {
303 Close(string.Empty);
304 }
305
306 }
307
308 /// <summary>
309 /// The server has decided not to allow the upgrade to a websocket for some reason. The Http 1.1 response that says Nay >:(
310 /// </summary>
311 /// <param name="pCode">HTTP Status reflecting the reason why</param>
312 /// <param name="pMessage">Textual reason for the upgrade fail</param>
313 private void FailUpgrade(OSHttpStatusCode pCode, string pMessage )
314 {
315 string handshakeResponse = string.Format(HandshakeDeclineText, (int)pCode, pMessage.Replace("\n", string.Empty).Replace("\r", string.Empty));
316 byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(handshakeResponse);
317 _networkContext.Stream.Write(bhandshakeResponse, 0, bhandshakeResponse.Length);
318 _networkContext.Stream.Flush();
319 _networkContext.Stream.Dispose();
320
321 UpgradeFailedDelegate d = OnUpgradeFailed;
322 if (d != null)
323 d(this,new UpgradeFailedEventArgs());
324 }
325
326
327 /// <summary>
328 /// This is our ugly Async OnReceive event handler.
329 /// This chunks the input stream based on the length of the provided buffer and processes out
330 /// as many frames as it can. It then moves the unprocessed data to the beginning of the buffer.
331 /// </summary>
332 /// <param name="ar">Our Async State from beginread</param>
333 private void OnReceive(IAsyncResult ar)
334 {
335 WebSocketState _socketState = ar.AsyncState as WebSocketState;
336 try
337 {
338 int bytesRead = _networkContext.Stream.EndRead(ar);
339 if (bytesRead == 0)
340 {
341 // Do Disconnect
342 _networkContext.Stream.Dispose();
343 _networkContext = null;
344 return;
345 }
346 _bufferPosition += bytesRead;
347
348 if (_bufferPosition > _bufferLength)
349 {
350 // Message too big for chunksize.. not sure how this happened...
351 //Close(string.Empty);
352 }
353
354 int offset = 0;
355 bool headerread = true;
356 int headerforwardposition = 0;
357 while (headerread && offset < bytesRead)
358 {
359 if (_socketState.FrameComplete)
360 {
361 WebsocketFrameHeader pheader = WebsocketFrameHeader.ZeroHeader;
362
363 headerread = WebSocketReader.TryReadHeader(_buffer, offset, _bufferPosition - offset, out pheader,
364 out headerforwardposition);
365 offset += headerforwardposition;
366
367 if (headerread)
368 {
369 _socketState.FrameComplete = false;
370
371 if (pheader.PayloadLen > 0)
372 {
373 if ((int) pheader.PayloadLen > _bufferPosition - offset)
374 {
375 byte[] writebytes = new byte[_bufferPosition - offset];
376
377 Buffer.BlockCopy(_buffer, offset, writebytes, 0, (int) _bufferPosition - offset);
378 _socketState.ExpectedBytes = (int) pheader.PayloadLen;
379 _socketState.ReceivedBytes.AddRange(writebytes);
380 _socketState.Header = pheader; // We need to add the header so that we can unmask it
381 offset += (int) _bufferPosition - offset;
382 }
383 else
384 {
385 byte[] writebytes = new byte[pheader.PayloadLen];
386 Buffer.BlockCopy(_buffer, offset, writebytes, 0, (int) pheader.PayloadLen);
387 WebSocketReader.Mask(pheader.Mask, writebytes);
388 pheader.IsMasked = false;
389 _socketState.FrameComplete = true;
390 _socketState.ReceivedBytes.AddRange(writebytes);
391 _socketState.Header = pheader;
392 offset += (int) pheader.PayloadLen;
393 }
394 }
395 else
396 {
397 pheader.Mask = 0;
398 _socketState.FrameComplete = true;
399 _socketState.Header = pheader;
400 }
401
402
403
404 if (_socketState.FrameComplete)
405 {
406 ProcessFrame(_socketState);
407 _socketState.Header.SetDefault();
408 _socketState.ReceivedBytes.Clear();
409 _socketState.ExpectedBytes = 0;
410
411 }
412
413 }
414 }
415 else
416 {
417 WebsocketFrameHeader frameHeader = _socketState.Header;
418 int bytesleft = _socketState.ExpectedBytes - _socketState.ReceivedBytes.Count;
419
420 if (bytesleft > _bufferPosition)
421 {
422 byte[] writebytes = new byte[_bufferPosition];
423
424 Buffer.BlockCopy(_buffer, offset, writebytes, 0, (int) _bufferPosition);
425 _socketState.ReceivedBytes.AddRange(writebytes);
426 _socketState.Header = frameHeader; // We need to add the header so that we can unmask it
427 offset += (int) _bufferPosition;
428 }
429 else
430 {
431 byte[] writebytes = new byte[_bufferPosition];
432 Buffer.BlockCopy(_buffer, offset, writebytes, 0, (int) _bufferPosition);
433 _socketState.FrameComplete = true;
434 _socketState.ReceivedBytes.AddRange(writebytes);
435 _socketState.Header = frameHeader;
436 offset += (int) _bufferPosition;
437 }
438 if (_socketState.FrameComplete)
439 {
440 ProcessFrame(_socketState);
441 _socketState.Header.SetDefault();
442 _socketState.ReceivedBytes.Clear();
443 _socketState.ExpectedBytes = 0;
444 // do some processing
445 }
446
447 }
448 }
449 if (offset > 0)
450 {
451 // If the buffer is maxed out.. we can just move the cursor. Nothing to move to the beginning.
452 if (offset <_buffer.Length)
453 Buffer.BlockCopy(_buffer, offset, _buffer, 0, _bufferPosition - offset);
454 _bufferPosition -= offset;
455 }
456 if (_networkContext.Stream != null && _networkContext.Stream.CanRead && !_closing)
457 {
458 _networkContext.Stream.BeginRead(_buffer, _bufferPosition, _bufferLength - _bufferPosition, OnReceive,
459 _socketState);
460 }
461 else
462 {
463 // We can't read the stream anymore...
464 }
465
466 }
467 catch (IOException fail)
468 {
469 Close(string.Empty);
470 }
471 catch (ObjectDisposedException fail)
472 {
473 Close(string.Empty);
474 }
475 }
476
477 /// <summary>
478 /// Sends a string to the other side
479 /// </summary>
480 /// <param name="message">the string message that is to be sent</param>
481 public void SendMessage(string message)
482 {
483 byte[] messagedata = Encoding.UTF8.GetBytes(message);
484 WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata };
485 textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text;
486 textMessageFrame.Header.IsEnd = true;
487 SendSocket(textMessageFrame.ToBytes());
488
489 }
490
491 public void SendData(byte[] data)
492 {
493 WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data};
494 dataMessageFrame.Header.IsEnd = true;
495 dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary;
496 SendSocket(dataMessageFrame.ToBytes());
497
498 }
499
500 /// <summary>
501 /// Writes raw bytes to the websocket. Unframed data will cause disconnection
502 /// </summary>
503 /// <param name="data"></param>
504 private void SendSocket(byte[] data)
505 {
506 if (!_closing)
507 {
508 try
509 {
510
511 _networkContext.Stream.Write(data, 0, data.Length);
512 }
513 catch (IOException)
514 {
515
516 }
517 }
518 }
519
520 /// <summary>
521 /// Sends a Ping check to the other side. The other side SHOULD respond as soon as possible with a pong frame. This interleaves with incoming fragmented frames.
522 /// </summary>
523 public void SendPingCheck()
524 {
525 WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] };
526 pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping;
527 pingFrame.Header.IsEnd = true;
528 _pingtime = Util.EnvironmentTickCount();
529 SendSocket(pingFrame.ToBytes());
530 }
531
532 /// <summary>
533 /// Closes the websocket connection. Sends a close message to the other side if it hasn't already done so.
534 /// </summary>
535 /// <param name="message"></param>
536 public void Close(string message)
537 {
538 if (_networkContext.Stream != null)
539 {
540 if (_networkContext.Stream.CanWrite)
541 {
542 byte[] messagedata = Encoding.UTF8.GetBytes(message);
543 WebSocketFrame closeResponseFrame = new WebSocketFrame()
544 {
545 Header = WebsocketFrameHeader.HeaderDefault(),
546 WebSocketPayload = messagedata
547 };
548 closeResponseFrame.Header.Opcode = WebSocketReader.OpCode.Close;
549 closeResponseFrame.Header.PayloadLen = (ulong) messagedata.Length;
550 closeResponseFrame.Header.IsEnd = true;
551 SendSocket(closeResponseFrame.ToBytes());
552 }
553 }
554 CloseDelegate closeD = OnClose;
555 if (closeD != null)
556 {
557 closeD(this, new CloseEventArgs());
558 }
559
560 _closing = true;
561 }
562
563 /// <summary>
564 /// Processes a websocket frame and triggers consumer events
565 /// </summary>
566 /// <param name="psocketState">We need to modify the websocket state here depending on the frame</param>
567 private void ProcessFrame(WebSocketState psocketState)
568 {
569 if (psocketState.Header.IsMasked)
570 {
571 byte[] unmask = psocketState.ReceivedBytes.ToArray();
572 WebSocketReader.Mask(psocketState.Header.Mask, unmask);
573 psocketState.ReceivedBytes = new List<byte>(unmask);
574 }
575
576 switch (psocketState.Header.Opcode)
577 {
578 case WebSocketReader.OpCode.Ping:
579 PingDelegate pingD = OnPing;
580 if (pingD != null)
581 {
582 pingD(this, new PingEventArgs());
583 }
584
585 WebSocketFrame pongFrame = new WebSocketFrame(){Header = WebsocketFrameHeader.HeaderDefault(),WebSocketPayload = new byte[0]};
586 pongFrame.Header.Opcode = WebSocketReader.OpCode.Pong;
587 pongFrame.Header.IsEnd = true;
588 SendSocket(pongFrame.ToBytes());
589 break;
590 case WebSocketReader.OpCode.Pong:
591
592 PongDelegate pongD = OnPong;
593 if (pongD != null)
594 {
595 pongD(this, new PongEventArgs(){PingResponseMS = Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(),_pingtime)});
596 }
597 break;
598 case WebSocketReader.OpCode.Binary:
599 if (!psocketState.Header.IsEnd) // Not done, so we need to store this and wait for the end frame.
600 {
601 psocketState.ContinuationFrame = new WebSocketFrame
602 {
603 Header = psocketState.Header,
604 WebSocketPayload =
605 psocketState.ReceivedBytes.ToArray()
606 };
607 }
608 else
609 {
610 // Send Done Event!
611 DataDelegate dataD = OnData;
612 if (dataD != null)
613 {
614 dataD(this,new WebsocketDataEventArgs(){Data = psocketState.ReceivedBytes.ToArray()});
615 }
616 }
617 break;
618 case WebSocketReader.OpCode.Text:
619 if (!psocketState.Header.IsEnd) // Not done, so we need to store this and wait for the end frame.
620 {
621 psocketState.ContinuationFrame = new WebSocketFrame
622 {
623 Header = psocketState.Header,
624 WebSocketPayload =
625 psocketState.ReceivedBytes.ToArray()
626 };
627 }
628 else
629 {
630 TextDelegate textD = OnText;
631 if (textD != null)
632 {
633 textD(this, new WebsocketTextEventArgs() { Data = Encoding.UTF8.GetString(psocketState.ReceivedBytes.ToArray()) });
634 }
635
636 // Send Done Event!
637 }
638 break;
639 case WebSocketReader.OpCode.Continue: // Continuation. Multiple frames worth of data for one message. Only valid when not using Control Opcodes
640 //Console.WriteLine("currhead " + psocketState.Header.IsEnd);
641 //Console.WriteLine("Continuation! " + psocketState.ContinuationFrame.Header.IsEnd);
642 byte[] combineddata = new byte[psocketState.ReceivedBytes.Count+psocketState.ContinuationFrame.WebSocketPayload.Length];
643 byte[] newdata = psocketState.ReceivedBytes.ToArray();
644 Buffer.BlockCopy(psocketState.ContinuationFrame.WebSocketPayload, 0, combineddata, 0, psocketState.ContinuationFrame.WebSocketPayload.Length);
645 Buffer.BlockCopy(newdata, 0, combineddata,
646 psocketState.ContinuationFrame.WebSocketPayload.Length, newdata.Length);
647 psocketState.ContinuationFrame.WebSocketPayload = combineddata;
648 psocketState.Header.PayloadLen = (ulong)combineddata.Length;
649 if (psocketState.Header.IsEnd)
650 {
651 if (psocketState.ContinuationFrame.Header.Opcode == WebSocketReader.OpCode.Text)
652 {
653 // Send Done event
654 TextDelegate textD = OnText;
655 if (textD != null)
656 {
657 textD(this, new WebsocketTextEventArgs() { Data = Encoding.UTF8.GetString(combineddata) });
658 }
659 }
660 else if (psocketState.ContinuationFrame.Header.Opcode == WebSocketReader.OpCode.Binary)
661 {
662 // Send Done event
663 DataDelegate dataD = OnData;
664 if (dataD != null)
665 {
666 dataD(this, new WebsocketDataEventArgs() { Data = combineddata });
667 }
668 }
669 else
670 {
671 // protocol violation
672 }
673 psocketState.ContinuationFrame = null;
674 }
675 break;
676 case WebSocketReader.OpCode.Close:
677 Close(string.Empty);
678
679 break;
680
681 }
682 psocketState.Header.SetDefault();
683 psocketState.ReceivedBytes.Clear();
684 psocketState.ExpectedBytes = 0;
685 }
686 public void Dispose()
687 {
688 if (_networkContext != null && _networkContext.Stream != null)
689 {
690 if (_networkContext.Stream.CanWrite)
691 _networkContext.Stream.Flush();
692 _networkContext.Stream.Close();
693 _networkContext.Stream.Dispose();
694 _networkContext.Stream = null;
695 }
696
697 if (_request != null && _request.InputStream != null)
698 {
699 _request.InputStream.Close();
700 _request.InputStream.Dispose();
701 _request = null;
702 }
703
704 if (_clientContext != null)
705 {
706 _clientContext.Close();
707 _clientContext = null;
708 }
709 }
710 }
711
712 /// <summary>
713 /// Reads a byte stream and returns Websocket frames.
714 /// </summary>
715 public class WebSocketReader
716 {
717 /// <summary>
718 /// Bit to determine if the frame read on the stream is the last frame in a sequence of fragmented frames
719 /// </summary>
720 private const byte EndBit = 0x80;
721
722 /// <summary>
723 /// These are the Frame Opcodes
724 /// </summary>
725 public enum OpCode
726 {
727 // Data Opcodes
728 Continue = 0x0,
729 Text = 0x1,
730 Binary = 0x2,
731
732 // Control flow Opcodes
733 Close = 0x8,
734 Ping = 0x9,
735 Pong = 0xA
736 }
737
738 /// <summary>
739 /// Masks and Unmasks data using the frame mask. Mask is applied per octal
740 /// Note: Frames from clients MUST be masked
741 /// Note: Frames from servers MUST NOT be masked
742 /// </summary>
743 /// <param name="pMask">Int representing 32 bytes of mask data. Mask is applied per octal</param>
744 /// <param name="pBuffer"></param>
745 public static void Mask(int pMask, byte[] pBuffer)
746 {
747 byte[] maskKey = BitConverter.GetBytes(pMask);
748 int currentMaskIndex = 0;
749 for (int i = 0; i < pBuffer.Length; i++)
750 {
751 pBuffer[i] = (byte)(pBuffer[i] ^ maskKey[currentMaskIndex]);
752 if (currentMaskIndex == 3)
753 {
754 currentMaskIndex = 0;
755 }
756 else
757 {
758 currentMaskIndex++;
759
760 }
761
762 }
763 }
764
765 /// <summary>
766 /// Attempts to read a header off the provided buffer. Returns true, exports a WebSocketFrameheader,
767 /// and an int to move the buffer forward when it reads a header. False when it can't read a header
768 /// </summary>
769 /// <param name="pBuffer">Bytes read from the stream</param>
770 /// <param name="pOffset">Starting place in the stream to begin trying to read from</param>
771 /// <param name="length">Lenth in the stream to try and read from. Provided for cases where the
772 /// buffer's length is larger then the data in it</param>
773 /// <param name="oHeader">Outputs the read WebSocket frame header</param>
774 /// <param name="moveBuffer">Informs the calling stream to move the buffer forward</param>
775 /// <returns>True if it got a header, False if it didn't get a header</returns>
776 public static bool TryReadHeader(byte[] pBuffer, int pOffset, int length, out WebsocketFrameHeader oHeader,
777 out int moveBuffer)
778 {
779 oHeader = WebsocketFrameHeader.ZeroHeader;
780 int minumheadersize = 2;
781 if (length > pBuffer.Length - pOffset)
782 throw new ArgumentOutOfRangeException("The Length specified was larger the byte array supplied");
783 if (length < minumheadersize)
784 {
785 moveBuffer = 0;
786 return false;
787 }
788
789 byte nibble1 = (byte)(pBuffer[pOffset] & 0xF0); //FIN/RSV1/RSV2/RSV3
790 byte nibble2 = (byte)(pBuffer[pOffset] & 0x0F); // Opcode block
791
792 oHeader = new WebsocketFrameHeader();
793 oHeader.SetDefault();
794
795 if ((nibble1 & WebSocketReader.EndBit) == WebSocketReader.EndBit)
796 {
797 oHeader.IsEnd = true;
798 }
799 else
800 {
801 oHeader.IsEnd = false;
802 }
803 //Opcode
804 oHeader.Opcode = (WebSocketReader.OpCode)nibble2;
805 //Mask
806 oHeader.IsMasked = Convert.ToBoolean((pBuffer[pOffset + 1] & 0x80) >> 7);
807
808 // Payload length
809 oHeader.PayloadLen = (byte)(pBuffer[pOffset + 1] & 0x7F);
810
811 int index = 2; // LargerPayload length starts at byte 3
812
813 switch (oHeader.PayloadLen)
814 {
815 case 126:
816 minumheadersize += 2;
817 if (length < minumheadersize)
818 {
819 moveBuffer = 0;
820 return false;
821 }
822 Array.Reverse(pBuffer, pOffset + index, 2); // two bytes
823 oHeader.PayloadLen = BitConverter.ToUInt16(pBuffer, pOffset + index);
824 index += 2;
825 break;
826 case 127: // we got more this is a bigger frame
827 // 8 bytes - uint64 - most significant bit 0 network byte order
828 minumheadersize += 8;
829 if (length < minumheadersize)
830 {
831 moveBuffer = 0;
832 return false;
833 }
834 Array.Reverse(pBuffer, pOffset + index, 8);
835 oHeader.PayloadLen = BitConverter.ToUInt64(pBuffer, pOffset + index);
836 index += 8;
837 break;
838
839 }
840 //oHeader.PayloadLeft = oHeader.PayloadLen; // Start the count in case it's chunked over the network. This is different then frame fragmentation
841 if (oHeader.IsMasked)
842 {
843 minumheadersize += 4;
844 if (length < minumheadersize)
845 {
846 moveBuffer = 0;
847 return false;
848 }
849 oHeader.Mask = BitConverter.ToInt32(pBuffer, pOffset + index);
850 index += 4;
851 }
852 moveBuffer = index;
853 return true;
854
855 }
856 }
857
858 /// <summary>
859 /// RFC6455 Websocket Frame
860 /// </summary>
861 public class WebSocketFrame
862 {
863 /*
864 * RFC6455
865nib 0 1 2 3 4 5 6 7
866byt 0 1 2 3
867dec 0 1 2 3
868 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
869 +-+-+-+-+-------+-+-------------+-------------------------------+
870 |F|R|R|R| opcode|M| Payload len | Extended payload length |
871 |I|S|S|S| (4) |A| (7) | (16/64) +
872 |N|V|V|V| |S| | (if payload len==126/127) |
873 | |1|2|3| |K| | +
874 +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
875 | Extended payload length continued, if payload len == 127 |
876 + - - - - - - - - - - - - - - - +-------------------------------+
877 | |Masking-key, if MASK set to 1 |
878 +-------------------------------+-------------------------------+
879 | Masking-key (continued) | Payload Data |
880 +-------------------------------- - - - - - - - - - - - - - - - +
881 : Payload Data continued ... :
882 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
883 | Payload Data continued ... |
884 +---------------------------------------------------------------+
885
886 * When reading these, the frames are possibly fragmented and interleaved with control frames
887 * the fragmented frames are not interleaved with data frames. Just control frames
888 */
889 public static readonly WebSocketFrame DefaultFrame = new WebSocketFrame(){Header = new WebsocketFrameHeader(),WebSocketPayload = new byte[0]};
890 public WebsocketFrameHeader Header;
891 public byte[] WebSocketPayload;
892
893 public byte[] ToBytes()
894 {
895 Header.PayloadLen = (ulong)WebSocketPayload.Length;
896 return Header.ToBytes(WebSocketPayload);
897 }
898
899 }
900
901 public struct WebsocketFrameHeader
902 {
903 //public byte CurrentMaskIndex;
904 /// <summary>
905 /// The last frame in a sequence of fragmented frames or the one and only frame for this message.
906 /// </summary>
907 public bool IsEnd;
908
909 /// <summary>
910 /// Returns whether the payload data is masked or not. Data from Clients MUST be masked, Data from Servers MUST NOT be masked
911 /// </summary>
912 public bool IsMasked;
913
914 /// <summary>
915 /// A set of cryptologically sound random bytes XoR-ed against the payload octally. Looped
916 /// </summary>
917 public int Mask;
918 /*
919byt 0 1 2 3
920 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
921 +---------------+---------------+---------------+---------------+
922 | Octal 1 | Octal 2 | Octal 3 | Octal 4 |
923 +---------------+---------------+---------------+---------------+
924*/
925
926
927 public WebSocketReader.OpCode Opcode;
928
929 public UInt64 PayloadLen;
930 //public UInt64 PayloadLeft;
931 // Payload is X + Y
932 //public UInt64 ExtensionDataLength;
933 //public UInt64 ApplicationDataLength;
934 public static readonly WebsocketFrameHeader ZeroHeader = WebsocketFrameHeader.HeaderDefault();
935
936 public void SetDefault()
937 {
938
939 //CurrentMaskIndex = 0;
940 IsEnd = true;
941 IsMasked = true;
942 Mask = 0;
943 Opcode = WebSocketReader.OpCode.Close;
944 // PayloadLeft = 0;
945 PayloadLen = 0;
946 // ExtensionDataLength = 0;
947 // ApplicationDataLength = 0;
948
949 }
950
951 /// <summary>
952 /// Returns a byte array representing the Frame header
953 /// </summary>
954 /// <param name="payload">This is the frame data payload. The header describes the size of the payload.
955 /// If payload is null, a Zero sized payload is assumed</param>
956 /// <returns>Returns a byte array representing the frame header</returns>
957 public byte[] ToBytes(byte[] payload)
958 {
959 List<byte> result = new List<byte>();
960
961 // Squeeze in our opcode and our ending bit.
962 result.Add((byte)((byte)Opcode | (IsEnd?0x80:0x00) ));
963
964 // Again with the three different byte interpretations of size..
965
966 //bytesize
967 if (PayloadLen <= 125)
968 {
969 result.Add((byte) PayloadLen);
970 } //Uint16
971 else if (PayloadLen <= ushort.MaxValue)
972 {
973 result.Add(126);
974 byte[] payloadLengthByte = BitConverter.GetBytes(Convert.ToUInt16(PayloadLen));
975 Array.Reverse(payloadLengthByte);
976 result.AddRange(payloadLengthByte);
977 } //UInt64
978 else
979 {
980 result.Add(127);
981 byte[] payloadLengthByte = BitConverter.GetBytes(PayloadLen);
982 Array.Reverse(payloadLengthByte);
983 result.AddRange(payloadLengthByte);
984 }
985
986 // Only add a payload if it's not null
987 if (payload != null)
988 {
989 result.AddRange(payload);
990 }
991 return result.ToArray();
992 }
993
994 /// <summary>
995 /// A Helper method to define the defaults
996 /// </summary>
997 /// <returns></returns>
998
999 public static WebsocketFrameHeader HeaderDefault()
1000 {
1001 return new WebsocketFrameHeader
1002 {
1003 //CurrentMaskIndex = 0,
1004 IsEnd = false,
1005 IsMasked = true,
1006 Mask = 0,
1007 Opcode = WebSocketReader.OpCode.Close,
1008 //PayloadLeft = 0,
1009 PayloadLen = 0,
1010 // ExtensionDataLength = 0,
1011 // ApplicationDataLength = 0
1012 };
1013 }
1014 }
1015
1016 public delegate void DataDelegate(object sender, WebsocketDataEventArgs data);
1017
1018 public delegate void TextDelegate(object sender, WebsocketTextEventArgs text);
1019
1020 public delegate void PingDelegate(object sender, PingEventArgs pingdata);
1021
1022 public delegate void PongDelegate(object sender, PongEventArgs pongdata);
1023
1024 public delegate void RegularHttpRequestDelegate(object sender, RegularHttpRequestEvnetArgs request);
1025
1026 public delegate void UpgradeCompletedDelegate(object sender, UpgradeCompletedEventArgs completeddata);
1027
1028 public delegate void UpgradeFailedDelegate(object sender, UpgradeFailedEventArgs faileddata);
1029
1030 public delegate void CloseDelegate(object sender, CloseEventArgs closedata);
1031
1032 public delegate bool ValidateHandshake(string pWebOrigin, string pWebSocketKey, string pHost);
1033
1034
1035 public class WebsocketDataEventArgs : EventArgs
1036 {
1037 public byte[] Data;
1038 }
1039
1040 public class WebsocketTextEventArgs : EventArgs
1041 {
1042 public string Data;
1043 }
1044
1045 public class PingEventArgs : EventArgs
1046 {
1047 /// <summary>
1048 /// The ping event can arbitrarily contain data
1049 /// </summary>
1050 public byte[] Data;
1051 }
1052
1053 public class PongEventArgs : EventArgs
1054 {
1055 /// <summary>
1056 /// The pong event can arbitrarily contain data
1057 /// </summary>
1058 public byte[] Data;
1059
1060 public int PingResponseMS;
1061
1062 }
1063
1064 public class RegularHttpRequestEvnetArgs : EventArgs
1065 {
1066
1067 }
1068
1069 public class UpgradeCompletedEventArgs : EventArgs
1070 {
1071
1072 }
1073
1074 public class UpgradeFailedEventArgs : EventArgs
1075 {
1076
1077 }
1078
1079 public class CloseEventArgs : EventArgs
1080 {
1081
1082 }
1083
1084
1085}
diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs
index ae7d515..293887f 100644
--- a/OpenSim/Framework/Servers/MainServer.cs
+++ b/OpenSim/Framework/Servers/MainServer.cs
@@ -230,6 +230,10 @@ namespace OpenSim.Framework.Servers
230 List<String> poll = httpServer.GetPollServiceHandlerKeys(); 230 List<String> poll = httpServer.GetPollServiceHandlerKeys();
231 foreach (String s in httpServer.GetHTTPHandlerKeys()) 231 foreach (String s in httpServer.GetHTTPHandlerKeys())
232 handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty)); 232 handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
233
234 handlers.AppendFormat("* JSONRPC:\n");
235 foreach (String s in httpServer.GetJsonRpcHandlerKeys())
236 handlers.AppendFormat("\t{0}\n", s);
233 237
234// handlers.AppendFormat("* Agent:\n"); 238// handlers.AppendFormat("* Agent:\n");
235// foreach (String s in httpServer.GetAgentHandlerKeys()) 239// foreach (String s in httpServer.GetAgentHandlerKeys())
diff --git a/OpenSim/Framework/Servers/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/Properties/AssemblyInfo.cs
index 021f63c..792c62e 100644
--- a/OpenSim/Framework/Servers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Servers/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index 9eb2281..65ccd10 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -27,16 +27,19 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
30using System.IO; 31using System.IO;
31using System.Reflection; 32using System.Reflection;
32using System.Text; 33using System.Text;
33using System.Text.RegularExpressions; 34using System.Text.RegularExpressions;
35using System.Threading;
34using log4net; 36using log4net;
35using log4net.Appender; 37using log4net.Appender;
36using log4net.Core; 38using log4net.Core;
37using log4net.Repository; 39using log4net.Repository;
38using Nini.Config; 40using Nini.Config;
39using OpenSim.Framework.Console; 41using OpenSim.Framework.Console;
42using OpenSim.Framework.Monitoring;
40 43
41namespace OpenSim.Framework.Servers 44namespace OpenSim.Framework.Servers
42{ 45{
@@ -168,6 +171,9 @@ namespace OpenSim.Framework.Servers
168 "General", false, "show info", "show info", "Show general information about the server", HandleShow); 171 "General", false, "show info", "show info", "Show general information about the server", HandleShow);
169 172
170 m_console.Commands.AddCommand( 173 m_console.Commands.AddCommand(
174 "General", false, "show version", "show version", "Show server version", HandleShow);
175
176 m_console.Commands.AddCommand(
171 "General", false, "show uptime", "show uptime", "Show server uptime", HandleShow); 177 "General", false, "show uptime", "show uptime", "Show server uptime", HandleShow);
172 178
173 m_console.Commands.AddCommand( 179 m_console.Commands.AddCommand(
@@ -206,6 +212,34 @@ namespace OpenSim.Framework.Servers
206 "General", false, "command-script", 212 "General", false, "command-script",
207 "command-script <script>", 213 "command-script <script>",
208 "Run a command script from file", HandleScript); 214 "Run a command script from file", HandleScript);
215
216 m_console.Commands.AddCommand(
217 "General", false, "show threads",
218 "show threads",
219 "Show thread status", HandleShow);
220
221 m_console.Commands.AddCommand(
222 "General", false, "threads abort",
223 "threads abort <thread-id>",
224 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
225
226 m_console.Commands.AddCommand(
227 "General", false, "threads show",
228 "threads show",
229 "Show thread status. Synonym for \"show threads\"",
230 (string module, string[] args) => Notice(GetThreadsReport()));
231
232 m_console.Commands.AddCommand(
233 "General", false, "force gc",
234 "force gc",
235 "Manually invoke runtime garbage collection. For debugging purposes",
236 HandleForceGc);
237 }
238
239 private void HandleForceGc(string module, string[] args)
240 {
241 Notice("Manually invoking runtime garbage collection");
242 GC.Collect();
209 } 243 }
210 244
211 public virtual void HandleShow(string module, string[] cmd) 245 public virtual void HandleShow(string module, string[] cmd)
@@ -222,9 +256,17 @@ namespace OpenSim.Framework.Servers
222 ShowInfo(); 256 ShowInfo();
223 break; 257 break;
224 258
259 case "version":
260 Notice(GetVersionText());
261 break;
262
225 case "uptime": 263 case "uptime":
226 Notice(GetUptimeReport()); 264 Notice(GetUptimeReport());
227 break; 265 break;
266
267 case "threads":
268 Notice(GetThreadsReport());
269 break;
228 } 270 }
229 } 271 }
230 272
@@ -537,6 +579,75 @@ namespace OpenSim.Framework.Servers
537 } 579 }
538 580
539 /// <summary> 581 /// <summary>
582 /// Get a report about the registered threads in this server.
583 /// </summary>
584 protected string GetThreadsReport()
585 {
586 // This should be a constant field.
587 string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
588
589 StringBuilder sb = new StringBuilder();
590 Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
591
592 sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
593
594 int timeNow = Environment.TickCount & Int32.MaxValue;
595
596 sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE");
597 sb.Append(Environment.NewLine);
598
599 foreach (Watchdog.ThreadWatchdogInfo twi in threads)
600 {
601 Thread t = twi.Thread;
602
603 sb.AppendFormat(
604 reportFormat,
605 t.ManagedThreadId,
606 t.Name,
607 timeNow - twi.LastTick,
608 timeNow - twi.FirstTick,
609 t.Priority,
610 t.ThreadState);
611
612 sb.Append("\n");
613 }
614
615 sb.Append("\n");
616
617 // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
618 // zero active threads.
619 int totalThreads = Process.GetCurrentProcess().Threads.Count;
620 if (totalThreads > 0)
621 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
622
623 sb.Append("Main threadpool (excluding script engine pools)\n");
624 sb.Append(Util.GetThreadPoolReport());
625
626 return sb.ToString();
627 }
628
629 public virtual void HandleThreadsAbort(string module, string[] cmd)
630 {
631 if (cmd.Length != 3)
632 {
633 MainConsole.Instance.Output("Usage: threads abort <thread-id>");
634 return;
635 }
636
637 int threadId;
638 if (!int.TryParse(cmd[2], out threadId))
639 {
640 MainConsole.Instance.Output("ERROR: Thread id must be an integer");
641 return;
642 }
643
644 if (Watchdog.AbortThread(threadId))
645 MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
646 else
647 MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
648 }
649
650 /// <summary>
540 /// Console output is only possible if a console has been established. 651 /// Console output is only possible if a console has been established.
541 /// That is something that cannot be determined within this class. So 652 /// That is something that cannot be determined within this class. So
542 /// all attempts to use the console MUST be verified. 653 /// all attempts to use the console MUST be verified.
diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
index 4c2f586..deae45c 100644
--- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
+++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
@@ -35,11 +35,12 @@ using HttpServer;
35using HttpServer.FormDecoders; 35using HttpServer.FormDecoders;
36using NUnit.Framework; 36using NUnit.Framework;
37using OpenSim.Framework.Servers.HttpServer; 37using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Tests.Common;
38 39
39namespace OpenSim.Framework.Servers.Tests 40namespace OpenSim.Framework.Servers.Tests
40{ 41{
41 [TestFixture] 42 [TestFixture]
42 public class OSHttpTests 43 public class OSHttpTests : OpenSimTestCase
43 { 44 {
44 // we need an IHttpClientContext for our tests 45 // we need an IHttpClientContext for our tests
45 public class TestHttpClientContext: IHttpClientContext 46 public class TestHttpClientContext: IHttpClientContext
@@ -69,6 +70,11 @@ namespace OpenSim.Framework.Servers.Tests
69 public void Close() { } 70 public void Close() { }
70 public bool EndWhenDone { get { return false;} set { return;}} 71 public bool EndWhenDone { get { return false;} set { return;}}
71 72
73 public HTTPNetworkContext GiveMeTheNetworkStreamIKnowWhatImDoing()
74 {
75 return new HTTPNetworkContext();
76 }
77
72 public event EventHandler<DisconnectedEventArgs> Disconnected = delegate { }; 78 public event EventHandler<DisconnectedEventArgs> Disconnected = delegate { };
73 /// <summary> 79 /// <summary>
74 /// A request have been received in the context. 80 /// A request have been received in the context.
diff --git a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
index 49e5061..480f2bb 100644
--- a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
+++ b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
@@ -29,11 +29,12 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using NUnit.Framework; 31using NUnit.Framework;
32using OpenSim.Tests.Common;
32 33
33namespace OpenSim.Framework.Servers.Tests 34namespace OpenSim.Framework.Servers.Tests
34{ 35{
35 [TestFixture] 36 [TestFixture]
36 public class VersionInfoTests 37 public class VersionInfoTests : OpenSimTestCase
37 { 38 {
38 [Test] 39 [Test]
39 public void TestVersionLength() 40 public void TestVersionLength()
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index bb094ed..737c14d 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,7 +29,7 @@ namespace OpenSim
29{ 29{
30 public class VersionInfo 30 public class VersionInfo
31 { 31 {
32 private const string VERSION_NUMBER = "0.7.5CM"; 32 private const string VERSION_NUMBER = "0.7.6CM";
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/Tests/AgentCircuitDataTest.cs b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
index 0dce414..95e9439 100644
--- a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
+++ b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
@@ -24,16 +24,17 @@
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
27using System.Collections.Generic; 28using System.Collections.Generic;
28using OpenMetaverse; 29using OpenMetaverse;
29using OpenMetaverse.StructuredData; 30using OpenMetaverse.StructuredData;
30using NUnit.Framework; 31using NUnit.Framework;
31 32using OpenSim.Tests.Common;
32 33
33namespace OpenSim.Framework.Tests 34namespace OpenSim.Framework.Tests
34{ 35{
35 [TestFixture] 36 [TestFixture]
36 public class AgentCircuitDataTest 37 public class AgentCircuitDataTest : OpenSimTestCase
37 { 38 {
38 private UUID AgentId; 39 private UUID AgentId;
39 private AvatarAppearance AvAppearance; 40 private AvatarAppearance AvAppearance;
diff --git a/OpenSim/Framework/Tests/AnimationTests.cs b/OpenSim/Framework/Tests/AnimationTests.cs
index 967a355..f3be81b 100644
--- a/OpenSim/Framework/Tests/AnimationTests.cs
+++ b/OpenSim/Framework/Tests/AnimationTests.cs
@@ -38,7 +38,7 @@ using Animation = OpenSim.Framework.Animation;
38namespace OpenSim.Framework.Tests 38namespace OpenSim.Framework.Tests
39{ 39{
40 [TestFixture] 40 [TestFixture]
41 public class AnimationTests 41 public class AnimationTests : OpenSimTestCase
42 { 42 {
43 private Animation anim1 = null; 43 private Animation anim1 = null;
44 private Animation anim2 = null; 44 private Animation anim2 = null;
diff --git a/OpenSim/Framework/Tests/AssetBaseTest.cs b/OpenSim/Framework/Tests/AssetBaseTest.cs
index 6db1aa0..25d2393 100644
--- a/OpenSim/Framework/Tests/AssetBaseTest.cs
+++ b/OpenSim/Framework/Tests/AssetBaseTest.cs
@@ -30,11 +30,12 @@ using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using NUnit.Framework; 31using NUnit.Framework;
32using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Tests.Common;
33 34
34namespace OpenSim.Framework.Tests 35namespace OpenSim.Framework.Tests
35{ 36{
36 [TestFixture] 37 [TestFixture]
37 public class AssetBaseTest 38 public class AssetBaseTest : OpenSimTestCase
38 { 39 {
39 [Test] 40 [Test]
40 public void TestContainsReferences() 41 public void TestContainsReferences()
diff --git a/OpenSim/Framework/Tests/CacheTests.cs b/OpenSim/Framework/Tests/CacheTests.cs
index c3613e6..c709860 100644
--- a/OpenSim/Framework/Tests/CacheTests.cs
+++ b/OpenSim/Framework/Tests/CacheTests.cs
@@ -28,11 +28,12 @@
28using System; 28using System;
29using NUnit.Framework; 29using NUnit.Framework;
30using OpenMetaverse; 30using OpenMetaverse;
31using OpenSim.Tests.Common;
31 32
32namespace OpenSim.Framework.Tests 33namespace OpenSim.Framework.Tests
33{ 34{
34 [TestFixture] 35 [TestFixture]
35 public class CacheTests 36 public class CacheTests : OpenSimTestCase
36 { 37 {
37 private Cache cache; 38 private Cache cache;
38 private UUID cacheItemUUID; 39 private UUID cacheItemUUID;
diff --git a/OpenSim/Framework/Tests/LocationTest.cs b/OpenSim/Framework/Tests/LocationTest.cs
index 2707afa..a56ecb4 100644
--- a/OpenSim/Framework/Tests/LocationTest.cs
+++ b/OpenSim/Framework/Tests/LocationTest.cs
@@ -26,11 +26,12 @@
26 */ 26 */
27 27
28using NUnit.Framework; 28using NUnit.Framework;
29using OpenSim.Tests.Common;
29 30
30namespace OpenSim.Framework.Tests 31namespace OpenSim.Framework.Tests
31{ 32{
32 [TestFixture] 33 [TestFixture]
33 public class LocationTest 34 public class LocationTest : OpenSimTestCase
34 { 35 {
35 [Test] 36 [Test]
36 public void locationRegionHandleRegionHandle() 37 public void locationRegionHandleRegionHandle()
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
index 6fde488..0fbdaf3 100644
--- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
+++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
@@ -32,11 +32,12 @@ using OpenMetaverse.StructuredData;
32using System; 32using System;
33using System.Globalization; 33using System.Globalization;
34using System.Threading; 34using System.Threading;
35using OpenSim.Tests.Common;
35 36
36namespace OpenSim.Framework.Tests 37namespace OpenSim.Framework.Tests
37{ 38{
38 [TestFixture] 39 [TestFixture]
39 public class MundaneFrameworkTests 40 public class MundaneFrameworkTests : OpenSimTestCase
40 { 41 {
41 private bool m_RegionSettingsOnSaveEventFired; 42 private bool m_RegionSettingsOnSaveEventFired;
42 private bool m_RegionLightShareDataOnSaveEventFired; 43 private bool m_RegionLightShareDataOnSaveEventFired;
@@ -302,10 +303,6 @@ namespace OpenSim.Framework.Tests
302 Culture.SetCurrentCulture(); 303 Culture.SetCurrentCulture();
303 Assert.That(Thread.CurrentThread.CurrentCulture.Name == ci.Name, "SetCurrentCulture failed to set thread culture to en-US"); 304 Assert.That(Thread.CurrentThread.CurrentCulture.Name == ci.Name, "SetCurrentCulture failed to set thread culture to en-US");
304 305
305 } 306 }
306
307
308
309 } 307 }
310} 308} \ No newline at end of file
311
diff --git a/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs b/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs
index 36bc6e7..82e13e5 100644
--- a/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs
+++ b/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs
@@ -31,11 +31,12 @@ using NUnit.Framework;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenMetaverse.StructuredData; 32using OpenMetaverse.StructuredData;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Tests.Common;
34 35
35namespace OpenSim.Framework.Tests 36namespace OpenSim.Framework.Tests
36{ 37{
37 [TestFixture] 38 [TestFixture]
38 public class PrimeNumberHelperTests 39 public class PrimeNumberHelperTests : OpenSimTestCase
39 { 40 {
40 [Test] 41 [Test]
41 public void TestGetPrime() 42 public void TestGetPrime()
diff --git a/OpenSim/Framework/Tests/UtilTest.cs b/OpenSim/Framework/Tests/UtilTest.cs
index f0d2a3f..11ca068 100644
--- a/OpenSim/Framework/Tests/UtilTest.cs
+++ b/OpenSim/Framework/Tests/UtilTest.cs
@@ -33,7 +33,7 @@ using OpenSim.Tests.Common;
33namespace OpenSim.Framework.Tests 33namespace OpenSim.Framework.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class UtilTests 36 public class UtilTests : OpenSimTestCase
37 { 37 {
38 [Test] 38 [Test]
39 public void VectorOperationTests() 39 public void VectorOperationTests()
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 48f3f8b..0545365 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -45,6 +45,7 @@ using System.Text.RegularExpressions;
45using System.Xml; 45using System.Xml;
46using System.Threading; 46using System.Threading;
47using log4net; 47using log4net;
48using log4net.Appender;
48using Nini.Config; 49using Nini.Config;
49using Nwc.XmlRpc; 50using Nwc.XmlRpc;
50using OpenMetaverse; 51using OpenMetaverse;
@@ -299,6 +300,25 @@ namespace OpenSim.Framework
299 x; 300 x;
300 } 301 }
301 302
303 // Clamp the maximum magnitude of a vector
304 public static Vector3 ClampV(Vector3 x, float max)
305 {
306 Vector3 ret = x;
307 float lenSq = x.LengthSquared();
308 if (lenSq > (max * max))
309 {
310 x = x / x.Length() * max;
311 }
312 return x;
313 }
314
315 // Inclusive, within range test (true if equal to the endpoints)
316 public static bool InRange<T>(T x, T min, T max)
317 where T : IComparable<T>
318 {
319 return x.CompareTo(max) <= 0 && x.CompareTo(min) >= 0;
320 }
321
302 public static uint GetNextXferID() 322 public static uint GetNextXferID()
303 { 323 {
304 uint id = 0; 324 uint id = 0;
@@ -809,9 +829,22 @@ namespace OpenSim.Framework
809 return "."; 829 return ".";
810 } 830 }
811 831
832 public static string logFile()
833 {
834 foreach (IAppender appender in LogManager.GetRepository().GetAppenders())
835 {
836 if (appender is FileAppender)
837 {
838 return ((FileAppender)appender).File;
839 }
840 }
841
842 return "./OpenSim.log";
843 }
844
812 public static string logDir() 845 public static string logDir()
813 { 846 {
814 return "."; 847 return Path.GetDirectoryName(logFile());
815 } 848 }
816 849
817 // From: http://coercedcode.blogspot.com/2008/03/c-generate-unique-filenames-within.html 850 // From: http://coercedcode.blogspot.com/2008/03/c-generate-unique-filenames-within.html
@@ -1651,7 +1684,13 @@ namespace OpenSim.Framework
1651 if (m_ThreadPool != null) 1684 if (m_ThreadPool != null)
1652 throw new InvalidOperationException("SmartThreadPool is already initialized"); 1685 throw new InvalidOperationException("SmartThreadPool is already initialized");
1653 1686
1654 m_ThreadPool = new SmartThreadPool(2000, maxThreads, 2); 1687 STPStartInfo startInfo = new STPStartInfo();
1688 startInfo.ThreadPoolName = "Util";
1689 startInfo.IdleTimeout = 2000;
1690 startInfo.MaxWorkerThreads = maxThreads;
1691 startInfo.MinWorkerThreads = 2;
1692
1693 m_ThreadPool = new SmartThreadPool(startInfo);
1655 } 1694 }
1656 1695
1657 public static int FireAndForgetCount() 1696 public static int FireAndForgetCount()
@@ -1724,7 +1763,7 @@ namespace OpenSim.Framework
1724 break; 1763 break;
1725 case FireAndForgetMethod.SmartThreadPool: 1764 case FireAndForgetMethod.SmartThreadPool:
1726 if (m_ThreadPool == null) 1765 if (m_ThreadPool == null)
1727 m_ThreadPool = new SmartThreadPool(2000, 15, 2); 1766 InitThreadPool(15);
1728 m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj }); 1767 m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj });
1729 break; 1768 break;
1730 case FireAndForgetMethod.Thread: 1769 case FireAndForgetMethod.Thread:
@@ -1753,12 +1792,16 @@ namespace OpenSim.Framework
1753 StringBuilder sb = new StringBuilder(); 1792 StringBuilder sb = new StringBuilder();
1754 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) 1793 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
1755 { 1794 {
1756 threadPoolUsed = "SmartThreadPool"; 1795 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
1757 maxThreads = m_ThreadPool.MaxThreads; 1796 if (m_ThreadPool != null)
1758 minThreads = m_ThreadPool.MinThreads; 1797 {
1759 inUseThreads = m_ThreadPool.InUseThreads; 1798 threadPoolUsed = "SmartThreadPool";
1760 allocatedThreads = m_ThreadPool.ActiveThreads; 1799 maxThreads = m_ThreadPool.MaxThreads;
1761 waitingCallbacks = m_ThreadPool.WaitingCallbacks; 1800 minThreads = m_ThreadPool.MinThreads;
1801 inUseThreads = m_ThreadPool.InUseThreads;
1802 allocatedThreads = m_ThreadPool.ActiveThreads;
1803 waitingCallbacks = m_ThreadPool.WaitingCallbacks;
1804 }
1762 } 1805 }
1763 else if ( 1806 else if (
1764 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem 1807 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
@@ -1863,6 +1906,12 @@ namespace OpenSim.Framework
1863 /// </summary> 1906 /// </summary>
1864 public static void PrintCallStack() 1907 public static void PrintCallStack()
1865 { 1908 {
1909 PrintCallStack(m_log.DebugFormat);
1910 }
1911
1912 public delegate void DebugPrinter(string msg, params Object[] parm);
1913 public static void PrintCallStack(DebugPrinter printer)
1914 {
1866 StackTrace stackTrace = new StackTrace(true); // get call stack 1915 StackTrace stackTrace = new StackTrace(true); // get call stack
1867 StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) 1916 StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
1868 1917
@@ -1870,7 +1919,7 @@ namespace OpenSim.Framework
1870 foreach (StackFrame stackFrame in stackFrames) 1919 foreach (StackFrame stackFrame in stackFrames)
1871 { 1920 {
1872 MethodBase mb = stackFrame.GetMethod(); 1921 MethodBase mb = stackFrame.GetMethod();
1873 m_log.DebugFormat("{0}.{1}:{2}", mb.DeclaringType, mb.Name, stackFrame.GetFileLineNumber()); // write method name 1922 printer("{0}.{1}:{2}", mb.DeclaringType, mb.Name, stackFrame.GetFileLineNumber()); // write method name
1874 } 1923 }
1875 } 1924 }
1876 1925
@@ -2096,6 +2145,17 @@ namespace OpenSim.Framework
2096 return firstName + "." + lastName + " " + "@" + uri.Authority; 2145 return firstName + "." + lastName + " " + "@" + uri.Authority;
2097 } 2146 }
2098 #endregion 2147 #endregion
2148
2149 /// <summary>
2150 /// Escapes the special characters used in "LIKE".
2151 /// </summary>
2152 /// <remarks>
2153 /// For example: EscapeForLike("foo_bar%baz") = "foo\_bar\%baz"
2154 /// </remarks>
2155 public static string EscapeForLike(string str)
2156 {
2157 return str.Replace("_", "\\_").Replace("%", "\\%");
2158 }
2099 } 2159 }
2100 2160
2101 public class DoubleQueue<T> where T:class 2161 public class DoubleQueue<T> where T:class
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 08e4023..e1cff69 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -236,18 +236,6 @@ namespace OpenSim
236 + "If an avatar name is given then only packets from that avatar are logged", 236 + "If an avatar name is given then only packets from that avatar are logged",
237 Debug); 237 Debug);
238 238
239 m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
240
241 m_console.Commands.AddCommand("Debug", false, "debug scene",
242 "debug scene active|collisions|physics|scripting|teleport true|false",
243 "Turn on scene debugging.",
244 "If active is false then main scene update and maintenance loops are suspended.\n"
245 + "If collisions is false then collisions with other objects are turned off.\n"
246 + "If physics is false then all physics objects are non-physical.\n"
247 + "If scripting is false then no scripting operations happen.\n"
248 + "If teleport is true then some extra teleport debug information is logged.",
249 Debug);
250
251 m_console.Commands.AddCommand("General", false, "change region", 239 m_console.Commands.AddCommand("General", false, "change region",
252 "change region <region name>", 240 "change region <region name>",
253 "Change current console region", ChangeSelectedRegion); 241 "Change current console region", ChangeSelectedRegion);
@@ -744,31 +732,6 @@ namespace OpenSim
744 732
745 break; 733 break;
746 734
747 case "scene":
748 if (args.Length == 4)
749 {
750 if (SceneManager.CurrentScene == null)
751 {
752 MainConsole.Instance.Output("Please use 'change region <regioname>' first");
753 }
754 else
755 {
756 string key = args[2];
757 string value = args[3];
758 SceneManager.CurrentScene.SetSceneCoreDebug(
759 new Dictionary<string, string>() { { key, value } });
760
761 MainConsole.Instance.OutputFormat("Set debug scene {0} = {1}", key, value);
762 }
763 }
764 else
765 {
766 MainConsole.Instance.Output(
767 "Usage: debug scene active|scripting|collisions|physics|teleport true|false");
768 }
769
770 break;
771
772 default: 735 default:
773 MainConsole.Instance.Output("Unknown debug command"); 736 MainConsole.Instance.Output("Unknown debug command");
774 break; 737 break;
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index bed9a49..3f63534 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -331,7 +331,7 @@ namespace OpenSim
331 /// <param name="regionInfo"></param> 331 /// <param name="regionInfo"></param>
332 /// <param name="portadd_flag"></param> 332 /// <param name="portadd_flag"></param>
333 /// <returns></returns> 333 /// <returns></returns>
334 public IClientNetworkServer CreateRegion(RegionInfo regionInfo, bool portadd_flag, out IScene scene) 334 public List<IClientNetworkServer> CreateRegion(RegionInfo regionInfo, bool portadd_flag, out IScene scene)
335 { 335 {
336 return CreateRegion(regionInfo, portadd_flag, false, out scene); 336 return CreateRegion(regionInfo, portadd_flag, false, out scene);
337 } 337 }
@@ -341,7 +341,7 @@ namespace OpenSim
341 /// </summary> 341 /// </summary>
342 /// <param name="regionInfo"></param> 342 /// <param name="regionInfo"></param>
343 /// <returns></returns> 343 /// <returns></returns>
344 public IClientNetworkServer CreateRegion(RegionInfo regionInfo, out IScene scene) 344 public List<IClientNetworkServer> CreateRegion(RegionInfo regionInfo, out IScene scene)
345 { 345 {
346 return CreateRegion(regionInfo, false, true, out scene); 346 return CreateRegion(regionInfo, false, true, out scene);
347 } 347 }
@@ -353,7 +353,7 @@ namespace OpenSim
353 /// <param name="portadd_flag"></param> 353 /// <param name="portadd_flag"></param>
354 /// <param name="do_post_init"></param> 354 /// <param name="do_post_init"></param>
355 /// <returns></returns> 355 /// <returns></returns>
356 public IClientNetworkServer CreateRegion(RegionInfo regionInfo, bool portadd_flag, bool do_post_init, out IScene mscene) 356 public List<IClientNetworkServer> CreateRegion(RegionInfo regionInfo, bool portadd_flag, bool do_post_init, out IScene mscene)
357 { 357 {
358 int port = regionInfo.InternalEndPoint.Port; 358 int port = regionInfo.InternalEndPoint.Port;
359 359
@@ -378,8 +378,8 @@ namespace OpenSim
378 Util.XmlRpcCommand(proxyUrl, "AddPort", port, port + proxyOffset, regionInfo.ExternalHostName); 378 Util.XmlRpcCommand(proxyUrl, "AddPort", port, port + proxyOffset, regionInfo.ExternalHostName);
379 } 379 }
380 380
381 IClientNetworkServer clientServer; 381 List<IClientNetworkServer> clientServers;
382 Scene scene = SetupScene(regionInfo, proxyOffset, Config, out clientServer); 382 Scene scene = SetupScene(regionInfo, proxyOffset, Config, out clientServers);
383 383
384 m_log.Info("[MODULES]: Loading Region's modules (old style)"); 384 m_log.Info("[MODULES]: Loading Region's modules (old style)");
385 385
@@ -483,8 +483,11 @@ namespace OpenSim
483 483
484 if (m_autoCreateClientStack) 484 if (m_autoCreateClientStack)
485 { 485 {
486 m_clientServers.Add(clientServer); 486 foreach (IClientNetworkServer clientserver in clientServers)
487 clientServer.Start(); 487 {
488 m_clientServers.Add(clientserver);
489 clientserver.Start();
490 }
488 } 491 }
489 492
490 if (scene.SnmpService != null) 493 if (scene.SnmpService != null)
@@ -504,7 +507,7 @@ namespace OpenSim
504 scene.Start(); 507 scene.Start();
505 scene.StartScripts(); 508 scene.StartScripts();
506 509
507 return clientServer; 510 return clientServers;
508 } 511 }
509 512
510 /// <summary> 513 /// <summary>
@@ -725,7 +728,7 @@ namespace OpenSim
725 /// <param name="regionInfo"></param> 728 /// <param name="regionInfo"></param>
726 /// <param name="clientServer"> </param> 729 /// <param name="clientServer"> </param>
727 /// <returns></returns> 730 /// <returns></returns>
728 protected Scene SetupScene(RegionInfo regionInfo, out IClientNetworkServer clientServer) 731 protected Scene SetupScene(RegionInfo regionInfo, out List<IClientNetworkServer> clientServer)
729 { 732 {
730 return SetupScene(regionInfo, 0, null, out clientServer); 733 return SetupScene(regionInfo, 0, null, out clientServer);
731 } 734 }
@@ -739,19 +742,20 @@ namespace OpenSim
739 /// <param name="clientServer"> </param> 742 /// <param name="clientServer"> </param>
740 /// <returns></returns> 743 /// <returns></returns>
741 protected Scene SetupScene( 744 protected Scene SetupScene(
742 RegionInfo regionInfo, int proxyOffset, IConfigSource configSource, out IClientNetworkServer clientServer) 745 RegionInfo regionInfo, int proxyOffset, IConfigSource configSource, out List<IClientNetworkServer> clientServer)
743 { 746 {
747 List<IClientNetworkServer> clientNetworkServers = null;
748
744 AgentCircuitManager circuitManager = new AgentCircuitManager(); 749 AgentCircuitManager circuitManager = new AgentCircuitManager();
745 IPAddress listenIP = regionInfo.InternalEndPoint.Address; 750 IPAddress listenIP = regionInfo.InternalEndPoint.Address;
746 //if (!IPAddress.TryParse(regionInfo.InternalEndPoint, out listenIP)) 751 //if (!IPAddress.TryParse(regionInfo.InternalEndPoint, out listenIP))
747 // listenIP = IPAddress.Parse("0.0.0.0"); 752 // listenIP = IPAddress.Parse("0.0.0.0");
748 753
749 uint port = (uint) regionInfo.InternalEndPoint.Port; 754 uint port = (uint) regionInfo.InternalEndPoint.Port;
750 755 IClientNetworkServer clientNetworkServer;
751 if (m_autoCreateClientStack) 756 if (m_autoCreateClientStack)
752 { 757 {
753 clientServer 758 clientNetworkServers = m_clientStackManager.CreateServers(
754 = m_clientStackManager.CreateServer(
755 listenIP, ref port, proxyOffset, regionInfo.m_allow_alternate_ports, configSource, 759 listenIP, ref port, proxyOffset, regionInfo.m_allow_alternate_ports, configSource,
756 circuitManager); 760 circuitManager);
757 } 761 }
@@ -766,9 +770,12 @@ namespace OpenSim
766 770
767 if (m_autoCreateClientStack) 771 if (m_autoCreateClientStack)
768 { 772 {
769 clientServer.AddScene(scene); 773 foreach (IClientNetworkServer clientnetserver in clientNetworkServers)
774 {
775 clientnetserver.AddScene(scene);
776 }
770 } 777 }
771 778 clientServer = clientNetworkServers;
772 scene.LoadWorldMap(); 779 scene.LoadWorldMap();
773 780
774 scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName); 781 scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName);
@@ -791,7 +798,7 @@ namespace OpenSim
791 798
792 return new Scene( 799 return new Scene(
793 regionInfo, circuitManager, sceneGridService, 800 regionInfo, circuitManager, sceneGridService,
794 simDataService, estateDataService, false, 801 simDataService, estateDataService,
795 Config, m_version); 802 Config, m_version);
796 } 803 }
797 804
diff --git a/OpenSim/Region/ClientStack/ClientStackManager.cs b/OpenSim/Region/ClientStack/ClientStackManager.cs
index 84ea0b3..299aabd 100644
--- a/OpenSim/Region/ClientStack/ClientStackManager.cs
+++ b/OpenSim/Region/ClientStack/ClientStackManager.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.Net; 30using System.Net;
30using System.Reflection; 31using System.Reflection;
31using log4net; 32using log4net;
@@ -38,39 +39,53 @@ namespace OpenSim.Region.ClientStack
38 { 39 {
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 41
41 private Type plugin; 42 private List<Type> plugin = new List<Type>();
42 private Assembly pluginAssembly; 43 private List<Assembly> pluginAssembly = new List<Assembly>();
43 44
44 public ClientStackManager(string dllName) 45 public ClientStackManager(string pDllName)
45 { 46 {
46 m_log.Info("[CLIENTSTACK]: Attempting to load " + dllName); 47 List<string> clientstacks = new List<string>();
47 48 if (pDllName.Contains(","))
48 try 49 {
50 clientstacks = new List<string>(pDllName.Split(','));
51 }
52 else
49 { 53 {
50 plugin = null; 54 clientstacks.Add(pDllName);
51 pluginAssembly = Assembly.LoadFrom(dllName); 55 }
56 foreach (string dllName in clientstacks)
57 {
58 m_log.Info("[CLIENTSTACK]: Attempting to load " + dllName);
52 59
53 foreach (Type pluginType in pluginAssembly.GetTypes()) 60 try
54 { 61 {
55 if (pluginType.IsPublic) 62 //plugin = null;
56 { 63 Assembly itemAssembly = Assembly.LoadFrom(dllName);
57 Type typeInterface = pluginType.GetInterface("IClientNetworkServer", true); 64 pluginAssembly.Add(itemAssembly);
58 65
59 if (typeInterface != null) 66 foreach (Type pluginType in itemAssembly.GetTypes())
67 {
68 if (pluginType.IsPublic)
60 { 69 {
61 m_log.Info("[CLIENTSTACK]: Added IClientNetworkServer Interface"); 70 Type typeInterface = pluginType.GetInterface("IClientNetworkServer", true);
62 plugin = pluginType; 71
63 return; 72 if (typeInterface != null)
73 {
74 m_log.Info("[CLIENTSTACK]: Added IClientNetworkServer Interface");
75 plugin.Add(pluginType);
76 break;
77 }
64 } 78 }
65 } 79 }
66 } 80 }
67 } catch (ReflectionTypeLoadException e) 81 catch (ReflectionTypeLoadException e)
68 {
69 foreach (Exception e2 in e.LoaderExceptions)
70 { 82 {
71 m_log.Error(e2.ToString()); 83 foreach (Exception e2 in e.LoaderExceptions)
84 {
85 m_log.Error(e2.ToString());
86 }
87 throw e;
72 } 88 }
73 throw e;
74 } 89 }
75 } 90 }
76 91
@@ -84,11 +99,11 @@ namespace OpenSim.Region.ClientStack
84 /// <param name="assetCache"></param> 99 /// <param name="assetCache"></param>
85 /// <param name="authenticateClass"></param> 100 /// <param name="authenticateClass"></param>
86 /// <returns></returns> 101 /// <returns></returns>
87 public IClientNetworkServer CreateServer( 102 public List<IClientNetworkServer> CreateServers(
88 IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, 103 IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port,
89 AgentCircuitManager authenticateClass) 104 AgentCircuitManager authenticateClass)
90 { 105 {
91 return CreateServer( 106 return CreateServers(
92 _listenIP, ref port, proxyPortOffset, allow_alternate_port, null, authenticateClass); 107 _listenIP, ref port, proxyPortOffset, allow_alternate_port, null, authenticateClass);
93 } 108 }
94 109
@@ -105,20 +120,24 @@ namespace OpenSim.Region.ClientStack
105 /// <param name="assetCache"></param> 120 /// <param name="assetCache"></param>
106 /// <param name="authenticateClass"></param> 121 /// <param name="authenticateClass"></param>
107 /// <returns></returns> 122 /// <returns></returns>
108 public IClientNetworkServer CreateServer( 123 public List<IClientNetworkServer> CreateServers(
109 IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, IConfigSource configSource, 124 IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, IConfigSource configSource,
110 AgentCircuitManager authenticateClass) 125 AgentCircuitManager authenticateClass)
111 { 126 {
127 List<IClientNetworkServer> servers = new List<IClientNetworkServer>();
112 if (plugin != null) 128 if (plugin != null)
113 { 129 {
114 IClientNetworkServer server = 130 for (int i = 0; i < plugin.Count; i++)
115 (IClientNetworkServer)Activator.CreateInstance(pluginAssembly.GetType(plugin.ToString())); 131 {
116 132 IClientNetworkServer server =
117 server.Initialise( 133 (IClientNetworkServer) Activator.CreateInstance(pluginAssembly[i].GetType(plugin[i].ToString()));
118 _listenIP, ref port, proxyPortOffset, allow_alternate_port, 134
119 configSource, authenticateClass); 135 server.Initialise(
120 136 _listenIP, ref port, proxyPortOffset, allow_alternate_port,
121 return server; 137 configSource, authenticateClass);
138 servers.Add(server);
139 }
140 return servers;
122 } 141 }
123 142
124 m_log.Error("[CLIENTSTACK]: Couldn't initialize a new server"); 143 m_log.Error("[CLIENTSTACK]: Couldn't initialize a new server");
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 2bb3d38..d7d4708 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -105,7 +105,6 @@ namespace OpenSim.Region.ClientStack.Linden
105 private static readonly string m_ResourceCostSelectedPath = "0103/"; 105 private static readonly string m_ResourceCostSelectedPath = "0103/";
106 private static readonly string m_UpdateAgentInformationPath = "0500/"; 106 private static readonly string m_UpdateAgentInformationPath = "0500/";
107 107
108
109 // These are callbacks which will be setup by the scene so that we can update scene data when we 108 // These are callbacks which will be setup by the scene so that we can update scene data when we
110 // receive capability calls 109 // receive capability calls
111 public NewInventoryItem AddNewInventoryItem = null; 110 public NewInventoryItem AddNewInventoryItem = null;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index d604cf6..ed8ec16 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -44,7 +44,7 @@ using OpenSim.Tests.Common.Mock;
44namespace OpenSim.Region.ClientStack.Linden.Tests 44namespace OpenSim.Region.ClientStack.Linden.Tests
45{ 45{
46 [TestFixture] 46 [TestFixture]
47 public class EventQueueTests 47 public class EventQueueTests : OpenSimTestCase
48 { 48 {
49 private TestScene m_scene; 49 private TestScene m_scene;
50 50
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
index 060a61c..d29a001 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index ca15e3e..f1fe6e1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -6576,19 +6576,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6576 #endregion 6576 #endregion
6577 6577
6578 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; 6578 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
6579 if (handlerAgentRequestSit != null)
6580 if (!(agentRequestSit.AgentData == null
6581 || agentRequestSit.TargetObject == null
6582 || agentRequestSit.TargetObject.TargetID == null
6583 || agentRequestSit.TargetObject.Offset == null))
6584 {
6585 var sp = m_scene.GetScenePresence(agentRequestSit.AgentData.AgentID);
6586 if (sp == null || sp.ParentID != 0) // ignore packet if agent is already sitting
6587 return true;
6588 6579
6589 handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, 6580 if (handlerAgentRequestSit != null)
6590 agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); 6581 handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID,
6591 } 6582 agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset);
6592 } 6583 }
6593 return true; 6584 return true;
6594 } 6585 }
@@ -12243,11 +12234,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12243 if (logPacket) 12234 if (logPacket)
12244 m_log.DebugFormat( 12235 m_log.DebugFormat(
12245 "[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}", 12236 "[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}",
12246 Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type); 12237 Name, SceneAgent.IsChildAgent ? "child" : "root ", Scene.Name, packet.Type);
12247 } 12238 }
12248 12239
12249 if (!ProcessPacketMethod(packet)) 12240 if (!ProcessPacketMethod(packet))
12250 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 12241 m_log.WarnFormat(
12242 "[CLIENT]: Unhandled packet {0} from {1} ({2}) in {3}. Ignoring.",
12243 packet.Type, Name, SceneAgent.IsChildAgent ? "child" : "root ", Scene.Name);
12251 } 12244 }
12252 12245
12253 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 12246 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 2aeb4cc..7035e38 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -204,9 +204,12 @@ namespace OpenMetaverse
204 { 204 {
205 UDPPacketBuffer buf; 205 UDPPacketBuffer buf;
206 206
207 if (UsePools) 207 // FIXME: Disabled for now as this causes issues with reused packet objects interfering with each other
208 buf = Pool.GetObject(); 208 // on Windows with m_asyncPacketHandling = true, though this has not been seen on Linux.
209 else 209 // Possibly some unexpected issue with fetching UDP data concurrently with multiple threads. Requires more investigation.
210// if (UsePools)
211// buf = Pool.GetObject();
212// else
210 buf = new UDPPacketBuffer(); 213 buf = new UDPPacketBuffer();
211 214
212 if (IsRunningInbound) 215 if (IsRunningInbound)
@@ -287,8 +290,8 @@ namespace OpenMetaverse
287 catch (ObjectDisposedException) { } 290 catch (ObjectDisposedException) { }
288 finally 291 finally
289 { 292 {
290 if (UsePools) 293// if (UsePools)
291 Pool.ReturnObject(buffer); 294// Pool.ReturnObject(buffer);
292 295
293 // Synchronous mode waits until the packet callback completes 296 // Synchronous mode waits until the packet callback completes
294 // before starting the receive to fetch another packet 297 // before starting the receive to fetch another packet
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
index af2f6f8..8f9dad3 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
index 5fcf376..7d9f581 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
@@ -43,7 +43,7 @@ using OpenSim.Tests.Common.Mock;
43namespace OpenSim.Region.ClientStack.LindenUDP.Tests 43namespace OpenSim.Region.ClientStack.LindenUDP.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class LLImageManagerTests 46 public class LLImageManagerTests : OpenSimTestCase
47 { 47 {
48 private AssetBase m_testImageAsset; 48 private AssetBase m_testImageAsset;
49 private Scene scene; 49 private Scene scene;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
index 0f88ec6..5f73a94 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
39 /// Tests for the LL packet handler 39 /// Tests for the LL packet handler
40 /// </summary> 40 /// </summary>
41 [TestFixture] 41 [TestFixture]
42 public class PacketHandlerTests 42 public class PacketHandlerTests : OpenSimTestCase
43 { 43 {
44// [Test] 44// [Test]
45// /// <summary> 45// /// <summary>
diff --git a/OpenSim/Region/ClientStack/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Properties/AssemblyInfo.cs
index e72bd86..0b6ee2f 100644
--- a/OpenSim/Region/ClientStack/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ClientStack/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 7332415..faee189 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -214,9 +214,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
214 public void HandleTaskItemUpdateFromTransaction( 214 public void HandleTaskItemUpdateFromTransaction(
215 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) 215 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
216 { 216 {
217 m_log.DebugFormat( 217// m_log.DebugFormat(
218 "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", 218// "[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 =
222 GetUserTransactions(remoteClient.AgentId); 222 GetUserTransactions(remoteClient.AgentId);
@@ -230,15 +230,17 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
230 /// </summary> 230 /// </summary>
231 /// <param name="remoteClient"></param> 231 /// <param name="remoteClient"></param>
232 /// <param name="assetID"></param> 232 /// <param name="assetID"></param>
233 /// <param name="transaction"></param> 233 /// <param name="transactionID"></param>
234 /// <param name="type"></param> 234 /// <param name="type"></param>
235 /// <param name="data"></param></param> 235 /// <param name="data"></param></param>
236 /// <param name="tempFile"></param> 236 /// <param name="tempFile"></param>
237 public void HandleUDPUploadRequest(IClientAPI remoteClient, 237 public void HandleUDPUploadRequest(IClientAPI remoteClient,
238 UUID assetID, UUID transaction, sbyte type, byte[] data, 238 UUID assetID, UUID transactionID, sbyte type, byte[] data,
239 bool storeLocal, bool tempFile) 239 bool storeLocal, bool tempFile)
240 { 240 {
241// m_log.Debug("HandleUDPUploadRequest - assetID: " + assetID.ToString() + " transaction: " + transaction.ToString() + " type: " + type.ToString() + " storelocal: " + storeLocal + " tempFile: " + tempFile); 241// m_log.DebugFormat(
242// "[ASSET TRANSACTION MODULE]: HandleUDPUploadRequest - assetID: {0}, transaction {1}, type {2}, storeLocal {3}, tempFile {4}, data.Length {5}",
243// assetID, transactionID, type, storeLocal, tempFile, data.Length);
242 244
243 if (((AssetType)type == AssetType.Texture || 245 if (((AssetType)type == AssetType.Texture ||
244 (AssetType)type == AssetType.Sound || 246 (AssetType)type == AssetType.Sound ||
@@ -274,8 +276,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
274 } 276 }
275 277
276 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); 278 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
277 AssetXferUploader uploader = transactions.RequestXferUploader(transaction); 279 AssetXferUploader uploader = transactions.RequestXferUploader(transactionID);
278 uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); 280 uploader.StartUpload(remoteClient, assetID, transactionID, type, data, storeLocal, tempFile);
279 } 281 }
280 282
281 /// <summary> 283 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index a0f1e8c..730643d 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -790,32 +790,43 @@ namespace OpenSim.Region.CoreModules.Asset
790 { 790 {
791 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 791 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
792 792
793 HashSet<UUID> uniqueUuids = new HashSet<UUID>();
793 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); 794 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>();
795
794 foreach (Scene s in m_Scenes) 796 foreach (Scene s in m_Scenes)
795 { 797 {
796 StampRegionStatusFile(s.RegionInfo.RegionID); 798 StampRegionStatusFile(s.RegionInfo.RegionID);
797 799
798 s.ForEachSOG(delegate(SceneObjectGroup e) 800 s.ForEachSOG(delegate(SceneObjectGroup e)
799 { 801 {
800 gatherer.GatherAssetUuids(e, assets); 802 gatherer.GatherAssetUuids(e, assets);
801 });
802 }
803 803
804 foreach (UUID assetID in assets.Keys) 804 foreach (UUID assetID in assets.Keys)
805 { 805 {
806 string filename = GetFileName(assetID.ToString()); 806 uniqueUuids.Add(assetID);
807 807
808 if (File.Exists(filename)) 808 string filename = GetFileName(assetID.ToString());
809 { 809
810 File.SetLastAccessTime(filename, DateTime.Now); 810 if (File.Exists(filename))
811 } 811 {
812 else if (storeUncached) 812 File.SetLastAccessTime(filename, DateTime.Now);
813 { 813 }
814 m_AssetService.Get(assetID.ToString()); 814 else if (storeUncached)
815 } 815 {
816 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
817 if (cachedAsset == null && assets[assetID] != AssetType.Unknown)
818 m_log.DebugFormat(
819 "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets",
820 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
821 }
822 }
823
824 assets.Clear();
825 });
816 } 826 }
817 827
818 return assets.Keys.Count; 828
829 return uniqueUuids.Count;
819 } 830 }
820 831
821 /// <summary> 832 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index 1c2bfd0..fd02b08 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -47,14 +47,16 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
47 /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness. 47 /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness.
48 /// </summary> 48 /// </summary>
49 [TestFixture] 49 [TestFixture]
50 public class FlotsamAssetCacheTests 50 public class FlotsamAssetCacheTests : OpenSimTestCase
51 { 51 {
52 protected TestScene m_scene; 52 protected TestScene m_scene;
53 protected FlotsamAssetCache m_cache; 53 protected FlotsamAssetCache m_cache;
54 54
55 [SetUp] 55 [SetUp]
56 public void SetUp() 56 public override void SetUp()
57 { 57 {
58 base.SetUp();
59
58 IConfigSource config = new IniConfigSource(); 60 IConfigSource config = new IniConfigSource();
59 61
60 config.AddConfig("Modules"); 62 config.AddConfig("Modules");
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index acd156e..6323160 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -722,15 +722,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
722 722
723 if (!silent) 723 if (!silent)
724 { 724 {
725 // Killing it here will cause the client to deselect it 725 if (so.HasPrivateAttachmentPoint)
726 // It then reappears on the avatar, deselected
727 // through the full update below
728 //
729 if (so.IsSelected)
730 {
731 m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId });
732 }
733 else if (so.HasPrivateAttachmentPoint)
734 { 726 {
735// m_log.DebugFormat( 727// m_log.DebugFormat(
736// "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}", 728// "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}",
@@ -745,7 +737,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
745 }); 737 });
746 } 738 }
747 739
748 so.IsSelected = false; // fudge.... 740 // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update
741 // will succeed, as that will not update if an attachment is selected.
742 so.IsSelected = false; // fudge....
743
749 so.ScheduleGroupForFullUpdate(); 744 so.ScheduleGroupForFullUpdate();
750 } 745 }
751 746
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 1adff7e..208bc9e 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -322,6 +322,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
322 322
323 if (asset != null) 323 if (asset != null)
324 { 324 {
325 // Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars
326 asset.ID = asset.FullID.ToString();
327
325 asset.Temporary = false; 328 asset.Temporary = false;
326 asset.Local = false; 329 asset.Local = false;
327 m_scene.AssetService.Store(asset); 330 m_scene.AssetService.Store(asset);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index e21547c..f090e15 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -39,7 +39,7 @@ using OpenSim.Tests.Common.Mock;
39namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory 39namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
40{ 40{
41 [TestFixture] 41 [TestFixture]
42 public class AvatarFactoryModuleTests 42 public class AvatarFactoryModuleTests : OpenSimTestCase
43 { 43 {
44 /// <summary> 44 /// <summary>
45 /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service. 45 /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service.
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
index 7a197f7..961117e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock;
40namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests 40namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class FriendsModuleTests 43 public class FriendsModuleTests : OpenSimTestCase
44 { 44 {
45 private FriendsModule m_fm; 45 private FriendsModule m_fm;
46 private TestScene m_scene; 46 private TestScene m_scene;
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index cc266df..1627f6c 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -153,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
153 if (sp != null && !sp.IsChildAgent) 153 if (sp != null && !sp.IsChildAgent)
154 { 154 {
155 // Local message 155 // Local message
156 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); 156// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
157 157
158 sp.ControllingClient.SendInstantMessage(im); 158 sp.ControllingClient.SendInstantMessage(im);
159 159
@@ -166,14 +166,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
166 // try child avatar second 166 // try child avatar second
167 foreach (Scene scene in m_Scenes) 167 foreach (Scene scene in m_Scenes)
168 { 168 {
169 //m_log.DebugFormat( 169// m_log.DebugFormat(
170 // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); 170// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
171 171
172 ScenePresence sp = scene.GetScenePresence(toAgentID); 172 ScenePresence sp = scene.GetScenePresence(toAgentID);
173 if (sp != null) 173 if (sp != null)
174 { 174 {
175 // Local message 175 // Local message
176 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); 176// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
177 177
178 sp.ControllingClient.SendInstantMessage(im); 178 sp.ControllingClient.SendInstantMessage(im);
179 179
@@ -183,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
183 } 183 }
184 } 184 }
185 185
186 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 186// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
187 187
188 SendGridInstantMessageViaXMLRPC(im, result); 188 SendGridInstantMessageViaXMLRPC(im, result);
189 } 189 }
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 3a44cc5..2d46276 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -189,20 +189,24 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
189 { 189 {
190 foreach (GridInstantMessage im in msglist) 190 foreach (GridInstantMessage im in msglist)
191 { 191 {
192 // client.SendInstantMessage(im); 192 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
193 193 // send it directly or else the item will be given twice
194 // Send through scene event manager so all modules get a chance 194 client.SendInstantMessage(im);
195 // to look at this message before it gets delivered. 195 else
196 // 196 {
197 // Needed for proper state management for stored group 197 // Send through scene event manager so all modules get a chance
198 // invitations 198 // to look at this message before it gets delivered.
199 // 199 //
200 200 // Needed for proper state management for stored group
201 im.offline = 1; 201 // invitations
202 202 //
203 Scene s = FindScene(client.AgentId); 203
204 if (s != null) 204 im.offline = 1;
205 s.EventManager.TriggerIncomingInstantMessage(im); 205
206 Scene s = FindScene(client.AgentId);
207 if (s != null)
208 s.EventManager.TriggerIncomingInstantMessage(im);
209 }
206 } 210 }
207 } 211 }
208 } 212 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index d0e88f6..4c85637 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -124,7 +124,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
124 SaveAssets = true; 124 SaveAssets = true;
125 } 125 }
126 126
127 protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) 127 protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut)
128 { 128 {
129 Exception reportedException = null; 129 Exception reportedException = null;
130 bool succeeded = true; 130 bool succeeded = true;
@@ -143,6 +143,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
143 m_saveStream.Close(); 143 m_saveStream.Close();
144 } 144 }
145 145
146 if (timedOut)
147 {
148 succeeded = false;
149 reportedException = new Exception("Loading assets timed out");
150 }
151
146 m_module.TriggerInventoryArchiveSaved( 152 m_module.TriggerInventoryArchiveSaved(
147 m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); 153 m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException);
148 } 154 }
@@ -350,7 +356,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
350 { 356 {
351 m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); 357 m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified");
352 358
353 ReceivedAllAssets(new List<UUID>(), new List<UUID>()); 359 ReceivedAllAssets(new List<UUID>(), new List<UUID>(), false);
354 } 360 }
355 } 361 }
356 catch (Exception) 362 catch (Exception)
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index 4cfa33d..ae58dfd 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -316,76 +316,74 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
316 } 316 }
317 } 317 }
318 318
319 // Disabled for now as it looks like http://opensimulator.org/mantis/view.php?id=6311 was fixed by fixes 319 // XXX: This code was placed here to try and accomodate RLV which moves given folders named #RLV/~<name>
320 // to inventory folder versioning allowing the viewer to move the received folder itself as happens on the 320 // to the requested folder, which in this case is #RLV. However, it is the viewer that appears to be
321 // LL grid. Doing it again server-side then wrongly does a second create and move 321 // response from renaming the #RLV/~example folder to ~example. For some reason this is not yet
322// // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~<name> 322 // happening, possibly because we are not sending the correct inventory update messages with the correct
323// // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis 323 // transaction IDs
324// // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously 324 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
325// // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here. 325 {
326// else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) 326 UUID destinationFolderID = UUID.Zero;
327// { 327
328// UUID destinationFolderID = UUID.Zero; 328 if (im.binaryBucket != null && im.binaryBucket.Length >= 16)
329// 329 {
330// if (im.binaryBucket != null && im.binaryBucket.Length >= 16) 330 destinationFolderID = new UUID(im.binaryBucket, 0);
331// { 331 }
332// destinationFolderID = new UUID(im.binaryBucket, 0); 332
333// } 333 if (destinationFolderID != UUID.Zero)
334// 334 {
335// if (destinationFolderID != UUID.Zero) 335 InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId);
336// { 336 if (destinationFolder == null)
337// InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); 337 {
338// if (destinationFolder == null) 338 m_log.WarnFormat(
339// { 339 "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist",
340// m_log.WarnFormat( 340 client.Name, scene.Name, destinationFolderID);
341// "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist", 341
342// client.Name, scene.Name, destinationFolderID); 342 return;
343// 343 }
344// return; 344
345// } 345 IInventoryService invService = scene.InventoryService;
346// 346
347// IInventoryService invService = scene.InventoryService; 347 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
348// 348
349// UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip 349 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
350// 350 item = invService.GetItem(item);
351// InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 351 InventoryFolderBase folder = null;
352// item = invService.GetItem(item); 352 UUID? previousParentFolderID = null;
353// InventoryFolderBase folder = null; 353
354// UUID? previousParentFolderID = null; 354 if (item != null) // It's an item
355// 355 {
356// if (item != null) // It's an item 356 previousParentFolderID = item.Folder;
357// { 357 item.Folder = destinationFolderID;
358// previousParentFolderID = item.Folder; 358
359// item.Folder = destinationFolderID; 359 invService.DeleteItems(item.Owner, new List<UUID>() { item.ID });
360// 360 scene.AddInventoryItem(client, item);
361// invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); 361 }
362// scene.AddInventoryItem(client, item); 362 else
363// } 363 {
364// else 364 folder = new InventoryFolderBase(inventoryID, client.AgentId);
365// { 365 folder = invService.GetFolder(folder);
366// folder = new InventoryFolderBase(inventoryID, client.AgentId); 366
367// folder = invService.GetFolder(folder); 367 if (folder != null) // It's a folder
368// 368 {
369// if (folder != null) // It's a folder 369 previousParentFolderID = folder.ParentID;
370// { 370 folder.ParentID = destinationFolderID;
371// previousParentFolderID = folder.ParentID; 371 invService.MoveFolder(folder);
372// folder.ParentID = destinationFolderID; 372 }
373// invService.MoveFolder(folder); 373 }
374// } 374
375// } 375 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
376// 376 if (previousParentFolderID != null)
377// // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). 377 {
378// if (previousParentFolderID != null) 378 InventoryFolderBase previousParentFolder
379// { 379 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
380// InventoryFolderBase previousParentFolder 380 previousParentFolder = invService.GetFolder(previousParentFolder);
381// = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); 381 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
382// previousParentFolder = invService.GetFolder(previousParentFolder); 382
383// scene.SendInventoryUpdate(client, previousParentFolder, true, true); 383 scene.SendInventoryUpdate(client, destinationFolder, true, true);
384// 384 }
385// scene.SendInventoryUpdate(client, destinationFolder, true, true); 385 }
386// } 386 }
387// }
388// }
389 else if ( 387 else if (
390 im.dialog == (byte)InstantMessageDialog.InventoryDeclined 388 im.dialog == (byte)InstantMessageDialog.InventoryDeclined
391 || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) 389 || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined)
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
new file mode 100644
index 0000000..d36f65a
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
@@ -0,0 +1,107 @@
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.Reflection;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.Packets;
36using OpenMetaverse.StructuredData;
37using OpenSim.Framework;
38using OpenSim.Region.Framework;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.Framework.DynamicAttributes.DAExampleModule
43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")]
45 public class DAExampleModule : INonSharedRegionModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private static readonly bool ENABLED = false; // enable for testing
50
51 protected Scene m_scene;
52 protected IDialogModule m_dialogMod;
53
54 public string Name { get { return "DAExample Module"; } }
55 public Type ReplaceableInterface { get { return null; } }
56
57 public void Initialise(IConfigSource source) {}
58
59 public void AddRegion(Scene scene)
60 {
61 if (ENABLED)
62 {
63 m_scene = scene;
64 m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove;
65 m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>();
66 }
67 }
68
69 public void RemoveRegion(Scene scene)
70 {
71 if (ENABLED)
72 {
73 m_scene.EventManager.OnSceneGroupMove -= OnSceneGroupMove;
74 }
75 }
76
77 public void RegionLoaded(Scene scene) {}
78
79 public void Close()
80 {
81 RemoveRegion(m_scene);
82 }
83
84 protected bool OnSceneGroupMove(UUID groupId, Vector3 delta)
85 {
86 OSDMap attrs = null;
87 SceneObjectPart sop = m_scene.GetSceneObjectPart(groupId);
88 if (!sop.DynAttrs.TryGetValue(Name, out attrs))
89 attrs = new OSDMap();
90
91 OSDInteger newValue;
92
93 if (!attrs.ContainsKey("moves"))
94 newValue = new OSDInteger(1);
95 else
96 newValue = new OSDInteger(((OSDInteger)attrs["moves"]).AsInteger() + 1);
97
98 attrs["moves"] = newValue;
99
100 sop.DynAttrs[Name] = attrs;
101
102 m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue));
103
104 return true;
105 }
106 }
107} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index f3a0b01..9b78b3b 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -212,11 +212,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
212 protected override GridRegion GetFinalDestination(GridRegion region) 212 protected override GridRegion GetFinalDestination(GridRegion region)
213 { 213 {
214 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); 214 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID);
215 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); 215 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionName, flags);
216 216
217 if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) 217 if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
218 { 218 {
219 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); 219 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region is hyperlink");
220 GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); 220 GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID);
221 if (real_destination != null) 221 if (real_destination != null)
222 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: GetFinalDestination serveruri -> {0}", real_destination.ServerURI); 222 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: GetFinalDestination serveruri -> {0}", real_destination.ServerURI);
diff --git a/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs
index 4004135..b9786ae 100644
--- a/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs
+++ b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using OpenSim.Region.Framework.Interfaces; 30using OpenSim.Region.Framework.Interfaces;
31using OpenMetaverse;
31 32
32namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander 33namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander
33{ 34{
@@ -152,6 +153,9 @@ namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander
152 case "Boolean": 153 case "Boolean":
153 m_args[i].ArgumentValue = Boolean.Parse(arg.ToString()); 154 m_args[i].ArgumentValue = Boolean.Parse(arg.ToString());
154 break; 155 break;
156 case "UUID":
157 m_args[i].ArgumentValue = UUID.Parse(arg.ToString());
158 break;
155 default: 159 default:
156 Console.WriteLine("ERROR: Unknown desired type for argument " + m_args[i].Name + " on command " + m_name); 160 Console.WriteLine("ERROR: Unknown desired type for argument " + m_args[i].Name + " on command " + m_name);
157 break; 161 break;
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index f8ec6de..7871eda 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
71 71
72 #region Internal functions 72 #region Internal functions
73 73
74 public AssetMetadata FetchMetadata(string url, UUID assetID) 74 private 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 + "/";
@@ -86,6 +86,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
86 return meta; 86 return meta;
87 } 87 }
88 88
89 private AssetBase FetchAsset(string url, UUID assetID)
90 {
91 // Test if it's already here
92 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
93 if (asset == null)
94 {
95 if (!url.EndsWith("/") && !url.EndsWith("="))
96 url = url + "/";
97
98 asset = m_scene.AssetService.Get(url + assetID.ToString());
99
100 //if (asset != null)
101 // m_log.DebugFormat("[HG ASSET MAPPER]: Fetched asset {0} of type {1} from {2} ", assetID, asset.Metadata.Type, url);
102 //else
103 // m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetch asset {0} from {1} ", assetID, url);
104
105 }
106
107 return asset;
108 }
109
89 public bool PostAsset(string url, AssetBase asset) 110 public bool PostAsset(string url, AssetBase asset)
90 { 111 {
91 if (asset != null) 112 if (asset != null)
@@ -228,11 +249,22 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
228 if (meta == null) 249 if (meta == null)
229 return; 250 return;
230 251
231 // The act of gathering UUIDs downloads the assets from the remote server 252 // The act of gathering UUIDs downloads some assets from the remote server
253 // but not all...
232 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 254 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
233 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); 255 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
234 uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); 256 uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids);
235 257 m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count);
258 bool success = true;
259 foreach (UUID uuid in ids.Keys)
260 if (FetchAsset(userAssetURL, uuid) == null)
261 success = false;
262
263 // maybe all pieces got here...
264 if (!success)
265 m_log.DebugFormat("[HG ASSET MAPPER]: Problems getting item {0} from asset server {1}", assetID, userAssetURL);
266 else
267 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully got item {0} from asset server {1}", assetID, userAssetURL);
236 } 268 }
237 269
238 270
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
index 21d8bd7..ac25a93 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
@@ -49,7 +49,7 @@ using OpenSim.Tests.Common.Mock;
49namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests 49namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
50{ 50{
51 [TestFixture] 51 [TestFixture]
52 public class InventoryAccessModuleTests 52 public class InventoryAccessModuleTests : OpenSimTestCase
53 { 53 {
54 protected TestScene m_scene; 54 protected TestScene m_scene;
55 protected BasicInventoryAccessModule m_iam; 55 protected BasicInventoryAccessModule m_iam;
@@ -57,8 +57,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
57 protected TestClient m_tc; 57 protected TestClient m_tc;
58 58
59 [SetUp] 59 [SetUp]
60 public void SetUp() 60 public override void SetUp()
61 { 61 {
62 base.SetUp();
63
62 m_iam = new BasicInventoryAccessModule(); 64 m_iam = new BasicInventoryAccessModule();
63 65
64 IConfigSource config = new IniConfigSource(); 66 IConfigSource config = new IniConfigSource();
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 86e7004..77e8b00 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -181,6 +181,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
181 181
182 m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); 182 m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query);
183 183
184 // searhc the user accounts service
184 List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); 185 List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
185 186
186 List<UserData> users = new List<UserData>(); 187 List<UserData> users = new List<UserData>();
@@ -196,6 +197,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
196 } 197 }
197 } 198 }
198 199
200 // search the local cache
201 foreach (UserData data in m_UserCache.Values)
202 if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
203 (data.FirstName.StartsWith(query) || data.LastName.StartsWith(query)))
204 users.Add(data);
205
199 AddAdditionalUsers(avatarID, query, users); 206 AddAdditionalUsers(avatarID, query, users);
200 207
201 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 208 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
@@ -433,6 +440,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
433 public void AddUser(UUID uuid, string first, string last, string homeURL) 440 public void AddUser(UUID uuid, string first, string last, string homeURL)
434 { 441 {
435 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); 442 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
443 if (homeURL == string.Empty)
444 return;
445
436 AddUser(uuid, homeURL + ";" + first + " " + last); 446 AddUser(uuid, homeURL + ";" + first + " " + last);
437 } 447 }
438 448
diff --git a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
index 5a8c4a2..f6353f9 100644
--- a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.7.5.*")] 33[assembly: AssemblyVersion("0.7.6.*")]
34[assembly: AssemblyFileVersion("1.0.0.0")] 34[assembly: AssemblyFileVersion("1.0.0.0")]
35 35
36[assembly: Addin("OpenSim.Region.CoreModules", "0.1")] 36[assembly: Addin("OpenSim.Region.CoreModules", "0.1")]
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index da59eab..60b7190 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -301,6 +301,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
301 UrlData urlData = m_RequestMap[request]; 301 UrlData urlData = m_RequestMap[request];
302 if (!urlData.requests[request].responseSent) 302 if (!urlData.requests[request].responseSent)
303 { 303 {
304 string responseBody = body;
305 if (urlData.requests[request].responseType.Equals("text/plain"))
306 {
307 string value;
308 if (urlData.requests[request].headers.TryGetValue("user-agent", out value))
309 {
310 if (value != null && value.IndexOf("MSIE") >= 0)
311 {
312 // wrap the html escaped response if the target client is IE
313 // It ignores "text/plain" if the body is html
314 responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>";
315 }
316 }
317 }
318
304 urlData.requests[request].responseCode = status; 319 urlData.requests[request].responseCode = status;
305 urlData.requests[request].responseBody = body; 320 urlData.requests[request].responseBody = body;
306 //urlData.requests[request].ev.Set(); 321 //urlData.requests[request].ev.Set();
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index f6e1d39..6bf50d2 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -41,7 +41,7 @@ using System.Linq.Expressions;
41namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms 41namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
42{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")]
44 class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms 44 public class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms
45 { 45 {
46 private static readonly ILog m_log = 46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 5836eb9..b61062f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -75,7 +75,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
75 public void Close() { } 75 public void Close() { }
76 public void PostInitialise() { } 76 public void PostInitialise() { }
77 77
78
79 ///<summary> 78 ///<summary>
80 /// 79 ///
81 ///</summary> 80 ///</summary>
@@ -136,7 +135,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
136 ///</summary> 135 ///</summary>
137 public void AddRegion(Scene scene) 136 public void AddRegion(Scene scene)
138 { 137 {
139 if (! m_enabled) 138 if (!m_enabled)
140 return; 139 return;
141 140
142 // Every shared region module has to maintain an indepedent list of 141 // Every shared region module has to maintain an indepedent list of
@@ -209,6 +208,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
209 208
210 using (Image mapTile = tileGenerator.CreateMapTile()) 209 using (Image mapTile = tileGenerator.CreateMapTile())
211 { 210 {
211 // XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there
212 // is no static map tile.
213 if (mapTile == null)
214 return;
215
212 using (MemoryStream stream = new MemoryStream()) 216 using (MemoryStream stream = new MemoryStream())
213 { 217 {
214 mapTile.Save(stream, ImageFormat.Jpeg); 218 mapTile.Save(stream, ImageFormat.Jpeg);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
index 32e47f9..69bac82 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
@@ -35,7 +35,6 @@ using NUnit.Framework;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using Nini.Config; 37using Nini.Config;
38
39using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; 38using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence;
40using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
41using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 40using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
@@ -44,11 +43,14 @@ using OpenSim.Tests.Common;
44namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
45{ 44{
46 [TestFixture] 45 [TestFixture]
47 public class PresenceConnectorsTests 46 public class PresenceConnectorsTests : OpenSimTestCase
48 { 47 {
49 LocalPresenceServicesConnector m_LocalConnector; 48 LocalPresenceServicesConnector m_LocalConnector;
50 private void SetUp() 49
50 public override void SetUp()
51 { 51 {
52 base.SetUp();
53
52 IConfigSource config = new IniConfigSource(); 54 IConfigSource config = new IniConfigSource();
53 config.AddConfig("Modules"); 55 config.AddConfig("Modules");
54 config.AddConfig("PresenceService"); 56 config.AddConfig("PresenceService");
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index ade5e76..fcfdf7c 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -570,13 +570,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver
570 570
571 // Validate User and Group UUID's 571 // Validate User and Group UUID's
572 572
573 if (!ResolveUserUuid(scene, parcel.OwnerID)) 573 if (parcel.IsGroupOwned)
574 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; 574 {
575 575 if (!ResolveGroupUuid(parcel.GroupID))
576 if (!ResolveGroupUuid(parcel.GroupID)) 576 {
577 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
578 parcel.GroupID = UUID.Zero;
579 parcel.IsGroupOwned = false;
580 }
581 }
582 else
577 { 583 {
578 parcel.GroupID = UUID.Zero; 584 if (!ResolveUserUuid(scene, parcel.OwnerID))
579 parcel.IsGroupOwned = false; 585 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
586
587 if (!ResolveGroupUuid(parcel.GroupID))
588 parcel.GroupID = UUID.Zero;
580 } 589 }
581 590
582 List<LandAccessEntry> accessList = new List<LandAccessEntry>(); 591 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
@@ -589,8 +598,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
589 parcel.ParcelAccessList = accessList; 598 parcel.ParcelAccessList = accessList;
590 599
591// m_log.DebugFormat( 600// m_log.DebugFormat(
592// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", 601// "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
593// parcel.Name, parcel.LocalID, parcel.Area); 602// parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
594 603
595 landData.Add(parcel); 604 landData.Add(parcel);
596 } 605 }
@@ -613,13 +622,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
613 /// <returns></returns> 622 /// <returns></returns>
614 private bool ResolveUserUuid(Scene scene, UUID uuid) 623 private bool ResolveUserUuid(Scene scene, UUID uuid)
615 { 624 {
616 if (!m_validUserUuids.ContainsKey(uuid)) 625 lock (m_validUserUuids)
617 { 626 {
618 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); 627 if (!m_validUserUuids.ContainsKey(uuid))
619 m_validUserUuids.Add(uuid, account != null); 628 {
620 } 629 // Note: we call GetUserAccount() inside the lock because this UserID is likely
630 // to occur many times, and we only want to query the users service once.
631 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid);
632 m_validUserUuids.Add(uuid, account != null);
633 }
621 634
622 return m_validUserUuids[uuid]; 635 return m_validUserUuids[uuid];
636 }
623 } 637 }
624 638
625 /// <summary> 639 /// <summary>
@@ -632,19 +646,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver
632 if (uuid == UUID.Zero) 646 if (uuid == UUID.Zero)
633 return true; // this means the object has no group 647 return true; // this means the object has no group
634 648
635 if (!m_validGroupUuids.ContainsKey(uuid)) 649 lock (m_validGroupUuids)
636 { 650 {
637 bool exists; 651 if (!m_validGroupUuids.ContainsKey(uuid))
638 652 {
639 if (m_groupsModule == null) 653 bool exists;
640 exists = false; 654 if (m_groupsModule == null)
641 else 655 {
642 exists = (m_groupsModule.GetGroupRecord(uuid) != null); 656 exists = false;
657 }
658 else
659 {
660 // Note: we call GetGroupRecord() inside the lock because this GroupID is likely
661 // to occur many times, and we only want to query the groups service once.
662 exists = (m_groupsModule.GetGroupRecord(uuid) != null);
663 }
664 m_validGroupUuids.Add(uuid, exists);
665 }
643 666
644 m_validGroupUuids.Add(uuid, exists); 667 return m_validGroupUuids[uuid];
645 } 668 }
646
647 return m_validGroupUuids[uuid];
648 } 669 }
649 670
650 /// Load an asset 671 /// Load an asset
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index d751b1c..367693d 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -167,7 +167,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
167 } 167 }
168 scenesGroup.CalcSceneLocations(); 168 scenesGroup.CalcSceneLocations();
169 169
170
171 m_archiveWriter = new TarArchiveWriter(m_saveStream); 170 m_archiveWriter = new TarArchiveWriter(m_saveStream);
172 171
173 try 172 try
@@ -216,7 +215,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
216 } 215 }
217 } 216 }
218 217
219
220 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) 218 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids)
221 { 219 {
222 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); 220 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
@@ -540,7 +538,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
540 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); 538 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
541 } 539 }
542 540
543
544 protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir) 541 protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir)
545 { 542 {
546 if (regionDir != string.Empty) 543 if (regionDir != string.Empty)
@@ -560,8 +557,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
560 foreach (ILandObject lo in landObjects) 557 foreach (ILandObject lo in landObjects)
561 { 558 {
562 LandData landData = lo.LandData; 559 LandData landData = lo.LandData;
563 string landDataPath = String.Format("{0}{1}{2}.xml", 560 string landDataPath
564 regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); 561 = String.Format("{0}{1}", regionDir, ArchiveConstants.CreateOarLandDataPath(landData));
565 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); 562 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
566 } 563 }
567 564
@@ -590,21 +587,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
590 } 587 }
591 } 588 }
592 589
593 protected void ReceivedAllAssets( 590 protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut)
594 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
595 { 591 {
596 foreach (UUID uuid in assetsNotFoundUuids) 592 string errorMessage;
593
594 if (timedOut)
597 { 595 {
598 m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); 596 errorMessage = "Loading assets timed out";
599 } 597 }
598 else
599 {
600 foreach (UUID uuid in assetsNotFoundUuids)
601 {
602 m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid);
603 }
600 604
601 // m_log.InfoFormat( 605 // m_log.InfoFormat(
602 // "[ARCHIVER]: Received {0} of {1} assets requested", 606 // "[ARCHIVER]: Received {0} of {1} assets requested",
603 // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); 607 // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count);
604 608
605 CloseArchive(String.Empty); 609 errorMessage = String.Empty;
610 }
611
612 CloseArchive(errorMessage);
606 } 613 }
607
608 614
609 /// <summary> 615 /// <summary>
610 /// Closes the archive and notifies that we're done. 616 /// Closes the archive and notifies that we're done.
@@ -629,6 +635,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver
629 635
630 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); 636 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage);
631 } 637 }
632
633 } 638 }
634} 639}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs
index 95d109c..c1ff94d 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs
@@ -150,12 +150,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver
150 m_log.InfoFormat("[ARCHIVER]: Added {0} assets to archive", m_assetsWritten); 150 m_log.InfoFormat("[ARCHIVER]: Added {0} assets to archive", m_assetsWritten);
151 } 151 }
152 152
153 /// <summary>
154 /// Only call this if you need to force a close on the underlying writer.
155 /// </summary>
156 public void ForceClose()
157 {
158 m_archiveWriter.Close();
159 }
160 } 153 }
161} 154}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index e2f8833..715bf51 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
50 /// Method called when all the necessary assets for an archive request have been received. 50 /// Method called when all the necessary assets for an archive request have been received.
51 /// </summary> 51 /// </summary>
52 public delegate void AssetsRequestCallback( 52 public delegate void AssetsRequestCallback(
53 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids); 53 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut);
54 54
55 enum RequestState 55 enum RequestState
56 { 56 {
@@ -148,7 +148,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
148 if (m_repliesRequired == 0) 148 if (m_repliesRequired == 0)
149 { 149 {
150 m_requestState = RequestState.Completed; 150 m_requestState = RequestState.Completed;
151 PerformAssetsRequestCallback(null); 151 PerformAssetsRequestCallback(false);
152 return; 152 return;
153 } 153 }
154 154
@@ -164,7 +164,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
164 164
165 protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args) 165 protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args)
166 { 166 {
167 bool close = true; 167 bool timedOut = true;
168 168
169 try 169 try
170 { 170 {
@@ -174,7 +174,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
174 // the final request came in (assuming that such a thing is possible) 174 // the final request came in (assuming that such a thing is possible)
175 if (m_requestState == RequestState.Completed) 175 if (m_requestState == RequestState.Completed)
176 { 176 {
177 close = false; 177 timedOut = false;
178 return; 178 return;
179 } 179 }
180 180
@@ -223,8 +223,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
223 } 223 }
224 finally 224 finally
225 { 225 {
226 if (close) 226 if (timedOut)
227 m_assetsArchiver.ForceClose(); 227 Util.FireAndForget(PerformAssetsRequestCallback, true);
228 } 228 }
229 } 229 }
230 230
@@ -290,7 +290,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
290 290
291 // We want to stop using the asset cache thread asap 291 // We want to stop using the asset cache thread asap
292 // as we now need to do the work of producing the rest of the archive 292 // as we now need to do the work of producing the rest of the archive
293 Util.FireAndForget(PerformAssetsRequestCallback); 293 Util.FireAndForget(PerformAssetsRequestCallback, false);
294 } 294 }
295 else 295 else
296 { 296 {
@@ -311,9 +311,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
311 { 311 {
312 Culture.SetCurrentCulture(); 312 Culture.SetCurrentCulture();
313 313
314 Boolean timedOut = (Boolean)o;
315
314 try 316 try
315 { 317 {
316 m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids); 318 m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids, timedOut);
317 } 319 }
318 catch (Exception e) 320 catch (Exception e)
319 { 321 {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 82f49b0..eec1cec 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -31,16 +31,19 @@ using System.IO;
31using System.Reflection; 31using System.Reflection;
32using System.Threading; 32using System.Threading;
33using log4net.Config; 33using log4net.Config;
34using Nini.Config;
34using NUnit.Framework; 35using NUnit.Framework;
35using OpenMetaverse; 36using OpenMetaverse;
36using OpenMetaverse.Assets; 37using OpenMetaverse.Assets;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Framework.Serialization; 39using OpenSim.Framework.Serialization;
39using OpenSim.Framework.Serialization.External; 40using OpenSim.Framework.Serialization.External;
41using OpenSim.Region.CoreModules.World.Land;
40using OpenSim.Region.CoreModules.World.Serialiser; 42using OpenSim.Region.CoreModules.World.Serialiser;
41using OpenSim.Region.CoreModules.World.Terrain; 43using OpenSim.Region.CoreModules.World.Terrain;
42using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Scenes.Serialization; 45using OpenSim.Region.Framework.Scenes.Serialization;
46using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups;
44using OpenSim.Tests.Common; 47using OpenSim.Tests.Common;
45using OpenSim.Tests.Common.Mock; 48using OpenSim.Tests.Common.Mock;
46using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; 49using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants;
@@ -69,9 +72,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
69 { 72 {
70 base.SetUp(); 73 base.SetUp();
71 74
72 // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later
73 new SceneManager();
74
75 m_archiverModule = new ArchiverModule(); 75 m_archiverModule = new ArchiverModule();
76 m_serialiserModule = new SerialiserModule(); 76 m_serialiserModule = new SerialiserModule();
77 TerrainModule terrainModule = new TerrainModule(); 77 TerrainModule terrainModule = new TerrainModule();
@@ -127,6 +127,53 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
127 127
128 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName }; 128 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName };
129 } 129 }
130
131 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
132 {
133 SceneObjectPart part1 = CreateSceneObjectPart1();
134 sog1 = new SceneObjectGroup(part1);
135 scene.AddNewSceneObject(sog1, false);
136
137 AssetNotecard nc = new AssetNotecard();
138 nc.BodyText = "Hello World!";
139 nc.Encode();
140 ncAssetUuid = UUID.Random();
141 UUID ncItemUuid = UUID.Random();
142 AssetBase ncAsset
143 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
144 m_scene.AssetService.Store(ncAsset);
145
146 TaskInventoryItem ncItem
147 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
148 SceneObjectPart part2 = CreateSceneObjectPart2();
149 sog2 = new SceneObjectGroup(part2);
150 part2.Inventory.AddInventoryItem(ncItem, true);
151
152 scene.AddNewSceneObject(sog2, false);
153 }
154
155 private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid)
156 {
157 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
158 {
159 using (BinaryReader br = new BinaryReader(resource))
160 {
161 // FIXME: Use the inspector instead
162 soundData = br.ReadBytes(99999999);
163 soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
164 string soundAssetFileName
165 = ArchiveConstants.ASSETS_PATH + soundUuid
166 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
167 tar.WriteFile(soundAssetFileName, soundData);
168
169 /*
170 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
171 scene.AssetService.Store(soundAsset);
172 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
173 */
174 }
175 }
176 }
130 177
131 /// <summary> 178 /// <summary>
132 /// Test saving an OpenSim Region Archive. 179 /// Test saving an OpenSim Region Archive.
@@ -204,30 +251,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
204 // TODO: Test presence of more files and contents of files. 251 // TODO: Test presence of more files and contents of files.
205 } 252 }
206 253
207 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
208 {
209 SceneObjectPart part1 = CreateSceneObjectPart1();
210 sog1 = new SceneObjectGroup(part1);
211 scene.AddNewSceneObject(sog1, false);
212
213 AssetNotecard nc = new AssetNotecard();
214 nc.BodyText = "Hello World!";
215 nc.Encode();
216 ncAssetUuid = UUID.Random();
217 UUID ncItemUuid = UUID.Random();
218 AssetBase ncAsset
219 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
220 m_scene.AssetService.Store(ncAsset);
221
222 TaskInventoryItem ncItem
223 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
224 SceneObjectPart part2 = CreateSceneObjectPart2();
225 sog2 = new SceneObjectGroup(part2);
226 part2.Inventory.AddInventoryItem(ncItem, true);
227
228 scene.AddNewSceneObject(sog2, false);
229 }
230
231 /// <summary> 254 /// <summary>
232 /// Test saving an OpenSim Region Archive with the no assets option 255 /// Test saving an OpenSim Region Archive with the no assets option
233 /// </summary> 256 /// </summary>
@@ -309,59 +332,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
309 } 332 }
310 333
311 /// <summary> 334 /// <summary>
312 /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g.
313 /// 2 can come after 3).
314 /// </summary>
315 [Test]
316 public void TestLoadOarUnorderedParts()
317 {
318 TestHelpers.InMethod();
319
320 UUID ownerId = TestHelpers.ParseTail(0xaaaa);
321
322 MemoryStream archiveWriteStream = new MemoryStream();
323 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
324
325 tar.WriteFile(
326 ArchiveConstants.CONTROL_FILE_PATH,
327 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
328
329 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
330 SceneObjectPart sop2
331 = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId);
332 SceneObjectPart sop3
333 = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId);
334
335 // Add the parts so they will be written out in reverse order to the oar
336 sog1.AddPart(sop3);
337 sop3.LinkNum = 3;
338 sog1.AddPart(sop2);
339 sop2.LinkNum = 2;
340
341 tar.WriteFile(
342 ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition),
343 SceneObjectSerializer.ToXml2Format(sog1));
344
345 tar.Close();
346
347 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
348
349 lock (this)
350 {
351 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
352 m_archiverModule.DearchiveRegion(archiveReadStream);
353 }
354
355 Assert.That(m_lastErrorMessage, Is.Null);
356
357 SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2");
358 Assert.That(part2.LinkNum, Is.EqualTo(2));
359
360 SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3");
361 Assert.That(part3.LinkNum, Is.EqualTo(3));
362 }
363
364 /// <summary>
365 /// Test loading an OpenSim Region Archive. 335 /// Test loading an OpenSim Region Archive.
366 /// </summary> 336 /// </summary>
367 [Test] 337 [Test]
@@ -435,50 +405,57 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
435 TestLoadedRegion(part1, soundItemName, soundData); 405 TestLoadedRegion(part1, soundItemName, soundData);
436 } 406 }
437 407
438 private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) 408 /// <summary>
409 /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g.
410 /// 2 can come after 3).
411 /// </summary>
412 [Test]
413 public void TestLoadOarUnorderedParts()
439 { 414 {
440 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) 415 TestHelpers.InMethod();
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 416
452 /* 417 UUID ownerId = TestHelpers.ParseTail(0xaaaa);
453 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
454 scene.AssetService.Store(soundAsset);
455 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
456 */
457 }
458 }
459 }
460 418
461 private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) 419 MemoryStream archiveWriteStream = new MemoryStream();
462 { 420 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
463 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
464 421
465 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); 422 tar.WriteFile(
466 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical"); 423 ArchiveConstants.CONTROL_FILE_PATH,
467 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal"); 424 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
468 Assert.That(
469 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
470 Assert.That(
471 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
472 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
473 Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
474 425
475 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; 426 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
476 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); 427 SceneObjectPart sop2
477 AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString()); 428 = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId);
478 Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null"); 429 SceneObjectPart sop3
479 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); 430 = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId);
480 431
481 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); 432 // Add the parts so they will be written out in reverse order to the oar
433 sog1.AddPart(sop3);
434 sop3.LinkNum = 3;
435 sog1.AddPart(sop2);
436 sop2.LinkNum = 2;
437
438 tar.WriteFile(
439 ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition),
440 SceneObjectSerializer.ToXml2Format(sog1));
441
442 tar.Close();
443
444 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
445
446 lock (this)
447 {
448 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
449 m_archiverModule.DearchiveRegion(archiveReadStream);
450 }
451
452 Assert.That(m_lastErrorMessage, Is.Null);
453
454 SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2");
455 Assert.That(part2.LinkNum, Is.EqualTo(2));
456
457 SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3");
458 Assert.That(part3.LinkNum, Is.EqualTo(3));
482 } 459 }
483 460
484 /// <summary> 461 /// <summary>
@@ -538,8 +515,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
538 SerialiserModule serialiserModule = new SerialiserModule(); 515 SerialiserModule serialiserModule = new SerialiserModule();
539 TerrainModule terrainModule = new TerrainModule(); 516 TerrainModule terrainModule = new TerrainModule();
540 517
541 m_sceneHelpers = new SceneHelpers(); 518 SceneHelpers m_sceneHelpers2 = new SceneHelpers();
542 TestScene scene2 = m_sceneHelpers.SetupScene(); 519 TestScene scene2 = m_sceneHelpers2.SetupScene();
543 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); 520 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule);
544 521
545 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is 522 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is
@@ -563,6 +540,71 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
563 } 540 }
564 541
565 /// <summary> 542 /// <summary>
543 /// Test OAR loading where the land parcel is group deeded.
544 /// </summary>
545 /// <remarks>
546 /// In this situation, the owner ID is set to the group ID.
547 /// </remarks>
548 [Test]
549 public void TestLoadOarDeededLand()
550 {
551 TestHelpers.InMethod();
552// TestHelpers.EnableLogging();
553
554 UUID landID = TestHelpers.ParseTail(0x10);
555
556 MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector();
557
558 IConfigSource configSource = new IniConfigSource();
559 IConfig config = configSource.AddConfig("Groups");
560 config.Set("Enabled", true);
561 config.Set("Module", "GroupsModule");
562 config.Set("DebugEnabled", true);
563 SceneHelpers.SetupSceneModules(
564 m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() });
565
566 // Create group in scene for loading
567 // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests.
568 UUID groupID
569 = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero);
570
571 // Construct OAR
572 MemoryStream oarStream = new MemoryStream();
573 TarArchiveWriter tar = new TarArchiveWriter(oarStream);
574
575 tar.WriteDir(ArchiveConstants.LANDDATA_PATH);
576 tar.WriteFile(
577 ArchiveConstants.CONTROL_FILE_PATH,
578 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
579
580 LandObject lo = new LandObject(groupID, true, null);
581 lo.SetLandBitmap(lo.BasicFullRegionLandBitmap());
582 LandData ld = lo.LandData;
583 ld.GlobalID = landID;
584
585 string ldPath = ArchiveConstants.CreateOarLandDataPath(ld);
586 tar.WriteFile(ldPath, LandDataSerializer.Serialize(ld, null));
587 tar.Close();
588
589 oarStream = new MemoryStream(oarStream.ToArray());
590
591 // Load OAR
592 lock (this)
593 {
594 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
595 m_archiverModule.DearchiveRegion(oarStream);
596 }
597
598 ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16);
599 LandData rLd = rLo.LandData;
600
601 Assert.That(rLd.GlobalID, Is.EqualTo(landID));
602 Assert.That(rLd.OwnerID, Is.EqualTo(groupID));
603 Assert.That(rLd.GroupID, Is.EqualTo(groupID));
604 Assert.That(rLd.IsGroupOwned, Is.EqualTo(true));
605 }
606
607 /// <summary>
566 /// Test loading the region settings of an OpenSim Region Archive. 608 /// Test loading the region settings of an OpenSim Region Archive.
567 /// </summary> 609 /// </summary>
568 [Test] 610 [Test]
@@ -781,9 +823,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
781 } 823 }
782 } 824 }
783 825
784
785 // Save OAR 826 // Save OAR
786
787 MemoryStream archiveWriteStream = new MemoryStream(); 827 MemoryStream archiveWriteStream = new MemoryStream();
788 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 828 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
789 829
@@ -800,7 +840,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
800 840
801 841
802 // Check that the OAR contains the expected data 842 // Check that the OAR contains the expected data
803
804 Assert.That(m_lastRequestId, Is.EqualTo(requestId)); 843 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
805 844
806 byte[] archive = archiveWriteStream.ToArray(); 845 byte[] archive = archiveWriteStream.ToArray();
@@ -892,7 +931,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
892 } 931 }
893 932
894 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); 933 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
895 SceneManager.Instance.ForEachScene(delegate(Scene scene) 934 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
896 { 935 {
897 scenesGroup.AddScene(scene); 936 scenesGroup.AddScene(scene);
898 }); 937 });
@@ -950,13 +989,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
950 989
951 // Delete the current objects, to test that they're loaded from the OAR and didn't 990 // Delete the current objects, to test that they're loaded from the OAR and didn't
952 // just remain in the scene. 991 // just remain in the scene.
953 SceneManager.Instance.ForEachScene(delegate(Scene scene) 992 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
954 { 993 {
955 scene.DeleteAllSceneObjects(); 994 scene.DeleteAllSceneObjects();
956 }); 995 });
957 996
958 // Create a "hole", to test that that the corresponding region isn't loaded from the OAR 997 // Create a "hole", to test that that the corresponding region isn't loaded from the OAR
959 SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]); 998 m_sceneHelpers.SceneManager.CloseScene(SceneManager.Instance.Scenes[1]);
960 999
961 1000
962 // Check thay the OAR file contains the expected data 1001 // Check thay the OAR file contains the expected data
@@ -971,10 +1010,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
971 1010
972 Assert.That(m_lastErrorMessage, Is.Null); 1011 Assert.That(m_lastErrorMessage, Is.Null);
973 1012
974 Assert.AreEqual(3, SceneManager.Instance.Scenes.Count); 1013 Assert.AreEqual(3, m_sceneHelpers.SceneManager.Scenes.Count);
975 1014
976 TestLoadedRegion(part1, soundItemName, soundData); 1015 TestLoadedRegion(part1, soundItemName, soundData);
977 } 1016 }
978 1017
1018 private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData)
1019 {
1020 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
1021
1022 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
1023 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical");
1024 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal");
1025 Assert.That(
1026 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
1027 Assert.That(
1028 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
1029 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
1030 Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
1031
1032 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0];
1033 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null");
1034 AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString());
1035 Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null");
1036 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
1037
1038 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels");
1039 }
979 } 1040 }
980} 1041} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
index 3b84d57..4d49794 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
@@ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
117 117
118 m_module.Scene.RegionInfo.RegionSettings.Save(); 118 m_module.Scene.RegionInfo.RegionSettings.Save();
119 m_module.TriggerRegionInfoChange(); 119 m_module.TriggerRegionInfoChange();
120 m_module.sendRegionInfoPacketToAll(); 120 m_module.sendRegionHandshakeToAll();
121 } 121 }
122 } 122 }
123 } 123 }
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index dc062b6..a5f5749 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -55,6 +55,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
55 55
56 protected EstateManagementCommands m_commands; 56 protected EstateManagementCommands m_commands;
57 57
58 /// <summary>
59 /// If false, region restart requests from the client are blocked even if they are otherwise legitimate.
60 /// </summary>
61 public bool AllowRegionRestartFromClient { get; set; }
62
58 private EstateTerrainXferHandler TerrainUploader; 63 private EstateTerrainXferHandler TerrainUploader;
59 public TelehubManager m_Telehub; 64 public TelehubManager m_Telehub;
60 65
@@ -64,6 +69,53 @@ namespace OpenSim.Region.CoreModules.World.Estate
64 69
65 private int m_delayCount = 0; 70 private int m_delayCount = 0;
66 71
72 #region Region Module interface
73
74 public string Name { get { return "EstateManagementModule"; } }
75
76 public Type ReplaceableInterface { get { return null; } }
77
78 public void Initialise(IConfigSource source)
79 {
80 AllowRegionRestartFromClient = true;
81
82 IConfig config = source.Configs["EstateManagement"];
83
84 if (config != null)
85 AllowRegionRestartFromClient = config.GetBoolean("AllowRegionRestartFromClient", true);
86 }
87
88 public void AddRegion(Scene scene)
89 {
90 Scene = scene;
91 Scene.RegisterModuleInterface<IEstateModule>(this);
92 Scene.EventManager.OnNewClient += EventManager_OnNewClient;
93 Scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight;
94
95 m_Telehub = new TelehubManager(scene);
96
97 m_commands = new EstateManagementCommands(this);
98 m_commands.Initialise();
99 }
100
101 public void RemoveRegion(Scene scene) {}
102
103 public void RegionLoaded(Scene scene)
104 {
105 // Sets up the sun module based no the saved Estate and Region Settings
106 // DO NOT REMOVE or the sun will stop working
107 scene.TriggerEstateSunUpdate();
108
109 UserManager = scene.RequestModuleInterface<IUserManagement>();
110 }
111
112 public void Close()
113 {
114 m_commands.Close();
115 }
116
117 #endregion
118
67 #region Packet Data Responders 119 #region Packet Data Responders
68 120
69 private void clientSendDetailedEstateData(IClientAPI remote_client, UUID invoice) 121 private void clientSendDetailedEstateData(IClientAPI remote_client, UUID invoice)
@@ -76,7 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
76 { 128 {
77 uint sun = 0; 129 uint sun = 0;
78 130
79 if (!Scene.RegionInfo.EstateSettings.UseGlobalTime) 131 if (Scene.RegionInfo.EstateSettings.FixedSun)
80 sun = (uint)(Scene.RegionInfo.EstateSettings.SunPosition * 1024.0) + 0x1800; 132 sun = (uint)(Scene.RegionInfo.EstateSettings.SunPosition * 1024.0) + 0x1800;
81 UUID estateOwner; 133 UUID estateOwner;
82 estateOwner = Scene.RegionInfo.EstateSettings.EstateOwner; 134 estateOwner = Scene.RegionInfo.EstateSettings.EstateOwner;
@@ -197,6 +249,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
197 Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; 249 Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture;
198 break; 250 break;
199 } 251 }
252
200 Scene.RegionInfo.RegionSettings.Save(); 253 Scene.RegionInfo.RegionSettings.Save();
201 TriggerRegionInfoChange(); 254 TriggerRegionInfoChange();
202 sendRegionInfoPacketToAll(); 255 sendRegionInfoPacketToAll();
@@ -228,6 +281,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
228 Scene.RegionInfo.RegionSettings.Elevation2NE = highValue; 281 Scene.RegionInfo.RegionSettings.Elevation2NE = highValue;
229 break; 282 break;
230 } 283 }
284
231 Scene.RegionInfo.RegionSettings.Save(); 285 Scene.RegionInfo.RegionSettings.Save();
232 TriggerRegionInfoChange(); 286 TriggerRegionInfoChange();
233 sendRegionHandshakeToAll(); 287 sendRegionHandshakeToAll();
@@ -268,6 +322,12 @@ namespace OpenSim.Region.CoreModules.World.Estate
268 322
269 private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds) 323 private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds)
270 { 324 {
325 if (!AllowRegionRestartFromClient)
326 {
327 remoteClient.SendAlertMessage("Region restart has been disabled on this simulator.");
328 return;
329 }
330
271 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); 331 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>();
272 if (restartModule != null) 332 if (restartModule != null)
273 { 333 {
@@ -352,6 +412,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
352 } 412 }
353 413
354 } 414 }
415
355 if ((estateAccessType & 8) != 0) // User remove 416 if ((estateAccessType & 8) != 0) // User remove
356 { 417 {
357 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) 418 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
@@ -383,6 +444,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
383 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 444 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
384 } 445 }
385 } 446 }
447
386 if ((estateAccessType & 16) != 0) // Group add 448 if ((estateAccessType & 16) != 0) // Group add
387 { 449 {
388 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) 450 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
@@ -650,7 +712,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
650 } 712 }
651 } 713 }
652 714
653 public void handleOnEstateManageTelehub (IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) 715 public void handleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
654 { 716 {
655 SceneObjectPart part; 717 SceneObjectPart part;
656 718
@@ -718,13 +780,18 @@ namespace OpenSim.Region.CoreModules.World.Estate
718 Scene.RegionInfo.RegionSettings.Save(); 780 Scene.RegionInfo.RegionSettings.Save();
719 TriggerRegionInfoChange(); 781 TriggerRegionInfoChange();
720 782
721 Scene.SetSceneCoreDebug( 783 ISceneCommandsModule scm = Scene.RequestModuleInterface<ISceneCommandsModule>();
722 new Dictionary<string, string>() { 784
723 { "scripting", (!disableScripts).ToString() }, 785 if (scm != null)
724 { "collisions", (!disableCollisions).ToString() }, 786 {
725 { "physics", (!disablePhysics).ToString() } 787 scm.SetSceneDebugOptions(
726 } 788 new Dictionary<string, string>() {
727 ); 789 { "scripting", (!disableScripts).ToString() },
790 { "collisions", (!disableCollisions).ToString() },
791 { "physics", (!disablePhysics).ToString() }
792 }
793 );
794 }
728 } 795 }
729 796
730 private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey) 797 private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey)
@@ -1066,6 +1133,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1066 { 1133 {
1067 Scene.RegionInfo.EstateSettings.UseGlobalTime = false; 1134 Scene.RegionInfo.EstateSettings.UseGlobalTime = false;
1068 Scene.RegionInfo.EstateSettings.SunPosition = (parms2 - 0x1800)/1024.0; 1135 Scene.RegionInfo.EstateSettings.SunPosition = (parms2 - 0x1800)/1024.0;
1136 // Warning: FixedSun should be set to True, otherwise this sun position won't be used.
1069 } 1137 }
1070 1138
1071 if ((parms1 & 0x00000010) != 0) 1139 if ((parms1 & 0x00000010) != 0)
@@ -1118,49 +1186,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
1118 1186
1119 #endregion 1187 #endregion
1120 1188
1121 #region Region Module interface
1122
1123 public string Name { get { return "EstateManagementModule"; } }
1124
1125 public Type ReplaceableInterface { get { return null; } }
1126
1127 public void Initialise(IConfigSource source) {}
1128
1129 public void AddRegion(Scene scene)
1130 {
1131 m_regionChangeTimer.AutoReset = false;
1132 m_regionChangeTimer.Interval = 2000;
1133 m_regionChangeTimer.Elapsed += RaiseRegionInfoChange;
1134
1135 Scene = scene;
1136 Scene.RegisterModuleInterface<IEstateModule>(this);
1137 Scene.EventManager.OnNewClient += EventManager_OnNewClient;
1138 Scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight;
1139
1140 m_Telehub = new TelehubManager(scene);
1141
1142 m_commands = new EstateManagementCommands(this);
1143 m_commands.Initialise();
1144 }
1145
1146 public void RemoveRegion(Scene scene) {}
1147
1148 public void RegionLoaded(Scene scene)
1149 {
1150 // Sets up the sun module based no the saved Estate and Region Settings
1151 // DO NOT REMOVE or the sun will stop working
1152 scene.TriggerEstateSunUpdate();
1153
1154 UserManager = scene.RequestModuleInterface<IUserManagement>();
1155 }
1156
1157 public void Close()
1158 {
1159 m_commands.Close();
1160 }
1161
1162 #endregion
1163
1164 #region Other Functions 1189 #region Other Functions
1165 1190
1166 public void changeWaterHeight(float height) 1191 public void changeWaterHeight(float height)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 1193057..b4f7d51 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -141,6 +141,7 @@ namespace OpenSim.Region.CoreModules.World.Land
141 m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy; 141 m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy;
142 m_scene.EventManager.OnLandBuy += EventManagerOnLandBuy; 142 m_scene.EventManager.OnLandBuy += EventManagerOnLandBuy;
143 m_scene.EventManager.OnNewClient += EventManagerOnNewClient; 143 m_scene.EventManager.OnNewClient += EventManagerOnNewClient;
144 m_scene.EventManager.OnMakeChildAgent += EventMakeChildAgent;
144 m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement; 145 m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement;
145 m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage; 146 m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage;
146 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; 147 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
@@ -221,6 +222,11 @@ namespace OpenSim.Region.CoreModules.World.Land
221 } 222 }
222 } 223 }
223 224
225 public void EventMakeChildAgent(ScenePresence avatar)
226 {
227 avatar.currentParcelUUID = UUID.Zero;
228 }
229
224 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 230 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
225 { 231 {
226 } 232 }
@@ -249,17 +255,15 @@ namespace OpenSim.Region.CoreModules.World.Land
249 newData.LocalID = local_id; 255 newData.LocalID = local_id;
250 ILandObject landobj = null; 256 ILandObject landobj = null;
251 257
258 ILandObject land;
252 lock (m_landList) 259 lock (m_landList)
253 { 260 {
254 if (m_landList.ContainsKey(local_id)) 261 if (m_landList.TryGetValue(local_id, out land))
255 { 262 land.LandData = newData;
256 m_landList[local_id].LandData = newData;
257 landobj = m_landList[local_id];
258// m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]);
259 }
260 } 263 }
261 if(landobj != null) 264
262 m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, landobj); 265 if (land != null)
266 m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, land);
263 } 267 }
264 268
265 public bool AllowedForcefulBans 269 public bool AllowedForcefulBans
@@ -584,7 +588,7 @@ namespace OpenSim.Region.CoreModules.World.Land
584 // Only now can we add the prim counts to the land object - we rely on the global ID which is generated 588 // Only now can we add the prim counts to the land object - we rely on the global ID which is generated
585 // as a random UUID inside LandData initialization 589 // as a random UUID inside LandData initialization
586 if (m_primCountModule != null) 590 if (m_primCountModule != null)
587 new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID); 591 new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID);
588 592
589 lock (m_landList) 593 lock (m_landList)
590 { 594 {
@@ -621,6 +625,7 @@ namespace OpenSim.Region.CoreModules.World.Land
621 /// <param name="local_id">Land.localID of the peice of land to remove.</param> 625 /// <param name="local_id">Land.localID of the peice of land to remove.</param>
622 public void removeLandObject(int local_id) 626 public void removeLandObject(int local_id)
623 { 627 {
628 ILandObject land;
624 lock (m_landList) 629 lock (m_landList)
625 { 630 {
626 for (int x = 0; x < 64; x++) 631 for (int x = 0; x < 64; x++)
@@ -637,9 +642,11 @@ namespace OpenSim.Region.CoreModules.World.Land
637 } 642 }
638 } 643 }
639 644
640 m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].LandData.GlobalID); 645 land = m_landList[local_id];
641 m_landList.Remove(local_id); 646 m_landList.Remove(local_id);
642 } 647 }
648
649 m_scene.EventManager.TriggerLandObjectRemoved(land.LandData.GlobalID);
643 } 650 }
644 651
645 /// <summary> 652 /// <summary>
@@ -1384,9 +1391,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1384 } 1391 }
1385 1392
1386 for (int i = 0; i < data.Count; i++) 1393 for (int i = 0; i < data.Count; i++)
1387 {
1388 IncomingLandObjectFromStorage(data[i]); 1394 IncomingLandObjectFromStorage(data[i]);
1389 }
1390 } 1395 }
1391 1396
1392 public void IncomingLandObjectFromStorage(LandData data) 1397 public void IncomingLandObjectFromStorage(LandData data)
@@ -1401,25 +1406,72 @@ namespace OpenSim.Region.CoreModules.World.Land
1401 1406
1402 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 1407 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
1403 { 1408 {
1404 ILandObject selectedParcel = null; 1409 if (localID != -1)
1405 lock (m_landList)
1406 { 1410 {
1407 m_landList.TryGetValue(localID, out selectedParcel); 1411 ILandObject selectedParcel = null;
1412 lock (m_landList)
1413 {
1414 m_landList.TryGetValue(localID, out selectedParcel);
1415 }
1416
1417 if (selectedParcel == null)
1418 return;
1419
1420 selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient);
1408 } 1421 }
1422 else
1423 {
1424 if (returnType != 1)
1425 {
1426 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: unknown return type {0}", returnType);
1427 return;
1428 }
1429
1430 // We get here when the user returns objects from the list of Top Colliders or Top Scripts.
1431 // In that case we receive specific object UUID's, but no parcel ID.
1432
1433 Dictionary<UUID, HashSet<SceneObjectGroup>> returns = new Dictionary<UUID, HashSet<SceneObjectGroup>>();
1434
1435 foreach (UUID groupID in taskIDs)
1436 {
1437 SceneObjectGroup obj = m_scene.GetSceneObjectGroup(groupID);
1438 if (obj != null)
1439 {
1440 if (!returns.ContainsKey(obj.OwnerID))
1441 returns[obj.OwnerID] = new HashSet<SceneObjectGroup>();
1442 returns[obj.OwnerID].Add(obj);
1443 }
1444 else
1445 {
1446 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: unknown object {0}", groupID);
1447 }
1448 }
1409 1449
1410 if (selectedParcel == null) return; 1450 int num = 0;
1451 foreach (HashSet<SceneObjectGroup> objs in returns.Values)
1452 num += objs.Count;
1453 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Returning {0} specific object(s)", num);
1411 1454
1412 selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient); 1455 foreach (HashSet<SceneObjectGroup> objs in returns.Values)
1456 {
1457 List<SceneObjectGroup> objs2 = new List<SceneObjectGroup>(objs);
1458 if (m_scene.Permissions.CanReturnObjects(null, remoteClient.AgentId, objs2))
1459 {
1460 m_scene.returnObjects(objs2.ToArray(), remoteClient.AgentId);
1461 }
1462 else
1463 {
1464 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: not permitted to return {0} object(s) belonging to user {1}",
1465 objs2.Count, objs2[0].OwnerID);
1466 }
1467 }
1468 }
1413 } 1469 }
1414 1470
1415 public void EventManagerOnNoLandDataFromStorage() 1471 public void EventManagerOnNoLandDataFromStorage()
1416 { 1472 {
1417 // called methods already have locks 1473 ResetSimLandObjects();
1418// lock (m_landList) 1474 CreateDefaultParcel();
1419 {
1420 ResetSimLandObjects();
1421 CreateDefaultParcel();
1422 }
1423 } 1475 }
1424 1476
1425 #endregion 1477 #endregion
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index fdac418..07d00c0 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -761,9 +761,10 @@ namespace OpenSim.Region.CoreModules.World.Land
761 int ty = min_y * 4; 761 int ty = min_y * 4;
762 if (ty > ((int)Constants.RegionSize - 1)) 762 if (ty > ((int)Constants.RegionSize - 1))
763 ty = ((int)Constants.RegionSize - 1); 763 ty = ((int)Constants.RegionSize - 1);
764
764 LandData.AABBMin = 765 LandData.AABBMin =
765 new Vector3((float) (min_x * 4), (float) (min_y * 4), 766 new Vector3(
766 (float) m_scene.Heightmap[tx, ty]); 767 (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
767 768
768 tx = max_x * 4; 769 tx = max_x * 4;
769 if (tx > ((int)Constants.RegionSize - 1)) 770 if (tx > ((int)Constants.RegionSize - 1))
@@ -771,9 +772,11 @@ namespace OpenSim.Region.CoreModules.World.Land
771 ty = max_y * 4; 772 ty = max_y * 4;
772 if (ty > ((int)Constants.RegionSize - 1)) 773 if (ty > ((int)Constants.RegionSize - 1))
773 ty = ((int)Constants.RegionSize - 1); 774 ty = ((int)Constants.RegionSize - 1);
774 LandData.AABBMax = 775
775 new Vector3((float) (max_x * 4), (float) (max_y * 4), 776 LandData.AABBMax
776 (float) m_scene.Heightmap[tx, ty]); 777 = new Vector3(
778 (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
779
777 LandData.Area = tempArea; 780 LandData.Area = tempArea;
778 } 781 }
779 782
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index 55b8227..771fdd2 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -490,11 +490,14 @@ namespace OpenSim.Region.CoreModules.World.Land
490 490
491 m_Scene.ForEachSOG(AddObject); 491 m_Scene.ForEachSOG(AddObject);
492 492
493 List<UUID> primcountKeys = new List<UUID>(m_PrimCounts.Keys); 493 lock (m_PrimCounts)
494 foreach (UUID k in primcountKeys)
495 { 494 {
496 if (!m_OwnerMap.ContainsKey(k)) 495 List<UUID> primcountKeys = new List<UUID>(m_PrimCounts.Keys);
497 m_PrimCounts.Remove(k); 496 foreach (UUID k in primcountKeys)
497 {
498 if (!m_OwnerMap.ContainsKey(k))
499 m_PrimCounts.Remove(k);
500 }
498 } 501 }
499 502
500 m_Tainted = false; 503 m_Tainted = false;
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
index b5ee4d2..0945b43 100644
--- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
@@ -41,7 +41,7 @@ using OpenSim.Tests.Common.Mock;
41namespace OpenSim.Region.CoreModules.World.Land.Tests 41namespace OpenSim.Region.CoreModules.World.Land.Tests
42{ 42{
43 [TestFixture] 43 [TestFixture]
44 public class PrimCountModuleTests 44 public class PrimCountModuleTests : OpenSimTestCase
45 { 45 {
46 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000"); 46 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000");
47 protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000"); 47 protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000");
@@ -60,8 +60,10 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
60 protected ILandObject m_lo2; 60 protected ILandObject m_lo2;
61 61
62 [SetUp] 62 [SetUp]
63 public void SetUp() 63 public override void SetUp()
64 { 64 {
65 base.SetUp();
66
65 m_pcm = new PrimCountModule(); 67 m_pcm = new PrimCountModule();
66 LandManagementModule lmm = new LandManagementModule(); 68 LandManagementModule lmm = new LandManagementModule();
67 m_scene = new SceneHelpers().SetupScene(); 69 m_scene = new SceneHelpers().SetupScene();
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index 8a422b0..e7065dc 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -77,42 +77,51 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
77 { 77 {
78 bool drawPrimVolume = true; 78 bool drawPrimVolume = true;
79 bool textureTerrain = false; 79 bool textureTerrain = false;
80 bool generateMaptiles = true;
81 Bitmap mapbmp;
80 82
81 try 83 try
82 { 84 {
83 IConfig startupConfig = m_config.Configs["Startup"]; 85 IConfig startupConfig = m_config.Configs["Startup"];
84 drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", drawPrimVolume); 86 drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", drawPrimVolume);
85 textureTerrain = startupConfig.GetBoolean("TextureOnMapTile", textureTerrain); 87 textureTerrain = startupConfig.GetBoolean("TextureOnMapTile", textureTerrain);
88 generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", generateMaptiles);
86 } 89 }
87 catch 90 catch
88 { 91 {
89 m_log.Warn("[MAPTILE]: Failed to load StartupConfig"); 92 m_log.Warn("[MAPTILE]: Failed to load StartupConfig");
90 } 93 }
91 94
92 if (textureTerrain) 95 if (generateMaptiles)
93 { 96 {
94 terrainRenderer = new TexturedMapTileRenderer(); 97 if (textureTerrain)
95 } 98 {
96 else 99 terrainRenderer = new TexturedMapTileRenderer();
97 { 100 }
98 terrainRenderer = new ShadedMapTileRenderer(); 101 else
99 } 102 {
100 terrainRenderer.Initialise(m_scene, m_config); 103 terrainRenderer = new ShadedMapTileRenderer();
104 }
101 105
102 Bitmap mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 106 terrainRenderer.Initialise(m_scene, m_config);
103 //long t = System.Environment.TickCount;
104 //for (int i = 0; i < 10; ++i) {
105 terrainRenderer.TerrainToBitmap(mapbmp);
106 //}
107 //t = System.Environment.TickCount - t;
108 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t);
109 107
108 mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
109 //long t = System.Environment.TickCount;
110 //for (int i = 0; i < 10; ++i) {
111 terrainRenderer.TerrainToBitmap(mapbmp);
112 //}
113 //t = System.Environment.TickCount - t;
114 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t);
110 115
111 if (drawPrimVolume) 116 if (drawPrimVolume)
117 {
118 DrawObjectVolume(m_scene, mapbmp);
119 }
120 }
121 else
112 { 122 {
113 DrawObjectVolume(m_scene, mapbmp); 123 mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID);
114 } 124 }
115
116 return mapbmp; 125 return mapbmp;
117 } 126 }
118 127
@@ -222,6 +231,49 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
222// } 231// }
223// } 232// }
224 233
234 private Bitmap FetchTexture(UUID id)
235 {
236 AssetBase asset = m_scene.AssetService.Get(id.ToString());
237
238 if (asset != null)
239 {
240 m_log.DebugFormat("[MAPTILE]: Static map image texture {0} found for {1}", id, m_scene.Name);
241 }
242 else
243 {
244 m_log.WarnFormat("[MAPTILE]: Static map image texture {0} not found for {1}", id, m_scene.Name);
245 return null;
246 }
247
248 ManagedImage managedImage;
249 Image image;
250
251 try
252 {
253 if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image))
254 return new Bitmap(image);
255 else
256 return null;
257 }
258 catch (DllNotFoundException)
259 {
260 m_log.ErrorFormat("[MAPTILE]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id);
261
262 }
263 catch (IndexOutOfRangeException)
264 {
265 m_log.ErrorFormat("[MAPTILE]: OpenJpeg was unable to decode this. Asset Data is empty for {0}", id);
266
267 }
268 catch (Exception)
269 {
270 m_log.ErrorFormat("[MAPTILE]: OpenJpeg was unable to decode this. Asset Data is empty for {0}", id);
271
272 }
273 return null;
274
275 }
276
225 private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp) 277 private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp)
226 { 278 {
227 int tc = 0; 279 int tc = 0;
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
index 396095a..03a96a4 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
@@ -44,14 +44,16 @@ using OpenSim.Tests.Common.Mock;
44namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests 44namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
45{ 45{
46 [TestFixture] 46 [TestFixture]
47 public class MoapTests 47 public class MoapTests : OpenSimTestCase
48 { 48 {
49 protected TestScene m_scene; 49 protected TestScene m_scene;
50 protected MoapModule m_module; 50 protected MoapModule m_module;
51 51
52 [SetUp] 52 [SetUp]
53 public void SetUp() 53 public override void SetUp()
54 { 54 {
55 base.SetUp();
56
55 m_module = new MoapModule(); 57 m_module = new MoapModule();
56 m_scene = new SceneHelpers().SetupScene(); 58 m_scene = new SceneHelpers().SetupScene();
57 SceneHelpers.SetupSceneModules(m_scene, m_module); 59 SceneHelpers.SetupSceneModules(m_scene, m_module);
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index ab8f143..9fc2daf 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -365,7 +365,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
365 365
366 if (mainParams.Count < 4) 366 if (mainParams.Count < 4)
367 { 367 {
368 m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>"); 368 //m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>");
369 m_console.OutputFormat("Usage: show part id <UUID-or-localID>");
369 return; 370 return;
370 } 371 }
371 372
@@ -405,6 +406,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
405 406
406 if (mainParams.Count < 5) 407 if (mainParams.Count < 5)
407 { 408 {
409 //m_console.OutputFormat("Usage: show part pos <start-coord> to <end-coord>");
408 m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>"); 410 m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>");
409 return; 411 return;
410 } 412 }
@@ -445,7 +447,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
445 447
446 if (mainParams.Count < 4) 448 if (mainParams.Count < 4)
447 { 449 {
448 m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>"); 450 m_console.OutputFormat("Usage: show part name [--regex] <name>");
451 //m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>");
449 return; 452 return;
450 } 453 }
451 454
@@ -577,6 +580,58 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
577 cdl.AddRow("Link number", sop.LinkNum); 580 cdl.AddRow("Link number", sop.LinkNum);
578 cdl.AddRow("Flags", sop.Flags); 581 cdl.AddRow("Flags", sop.Flags);
579 582
583 if (showFull)
584 {
585 PrimitiveBaseShape s = sop.Shape;
586 cdl.AddRow("FlexiDrag", s.FlexiDrag);
587 cdl.AddRow("FlexiEntry", s.FlexiEntry);
588 cdl.AddRow("FlexiForce", string.Format("<{0},{1},{2}>", s.FlexiForceX, s.FlexiForceY, s.FlexiForceZ));
589 cdl.AddRow("FlexiGravity", s.FlexiGravity);
590 cdl.AddRow("FlexiSoftness", s.FlexiSoftness);
591 cdl.AddRow("HollowShape", s.HollowShape);
592 cdl.AddRow(
593 "LightColor",
594 string.Format("<{0},{1},{2},{3}>", s.LightColorR, s.LightColorB, s.LightColorG, s.LightColorA));
595 cdl.AddRow("LightCutoff", s.LightCutoff);
596 cdl.AddRow("LightEntry", s.LightEntry);
597 cdl.AddRow("LightFalloff", s.LightFalloff);
598 cdl.AddRow("LightIntensity", s.LightIntensity);
599 cdl.AddRow("LightRadius", s.LightRadius);
600 cdl.AddRow("Media", string.Format("{0} entries", s.Media != null ? s.Media.Count.ToString() : "n/a"));
601 cdl.AddRow("PathBegin", s.PathBegin);
602 cdl.AddRow("PathEnd", s.PathEnd);
603 cdl.AddRow("PathCurve", s.PathCurve);
604 cdl.AddRow("PathRadiusOffset", s.PathRadiusOffset);
605 cdl.AddRow("PathRevolutions", s.PathRevolutions);
606 cdl.AddRow("PathScale", string.Format("<{0},{1}>", s.PathScaleX, s.PathScaleY));
607 cdl.AddRow("PathSkew", string.Format("<{0},{1}>", s.PathShearX, s.PathShearY));
608 cdl.AddRow("FlexiDrag", s.PathSkew);
609 cdl.AddRow("PathTaper", string.Format("<{0},{1}>", s.PathTaperX, s.PathTaperY));
610 cdl.AddRow("PathTwist", s.PathTwist);
611 cdl.AddRow("PathTwistBegin", s.PathTwistBegin);
612 cdl.AddRow("PCode", s.PCode);
613 cdl.AddRow("ProfileBegin", s.ProfileBegin);
614 cdl.AddRow("ProfileEnd", s.ProfileEnd);
615 cdl.AddRow("ProfileHollow", s.ProfileHollow);
616 cdl.AddRow("ProfileShape", s.ProfileShape);
617 cdl.AddRow("ProjectionAmbiance", s.ProjectionAmbiance);
618 cdl.AddRow("ProjectionEntry", s.ProjectionEntry);
619 cdl.AddRow("ProjectionFocus", s.ProjectionFocus);
620 cdl.AddRow("ProjectionFOV", s.ProjectionFOV);
621 cdl.AddRow("ProjectionTextureUUID", s.ProjectionTextureUUID);
622 cdl.AddRow("Scale", s.Scale);
623 cdl.AddRow(
624 "SculptData",
625 string.Format("{0} bytes", s.SculptData != null ? s.SculptData.Length.ToString() : "n/a"));
626 cdl.AddRow("SculptEntry", s.SculptEntry);
627 cdl.AddRow("SculptTexture", s.SculptTexture);
628 cdl.AddRow("SculptType", s.SculptType);
629 cdl.AddRow("State", s.State);
630
631 // TODO, unpack and display texture entries
632 //cdl.AddRow("Textures", string.Format("{0} entries", s.Textures.
633 }
634
580 object itemsOutput; 635 object itemsOutput;
581 if (showFull) 636 if (showFull)
582 { 637 {
@@ -588,7 +643,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
588 itemsOutput = sop.Inventory.Count; 643 itemsOutput = sop.Inventory.Count;
589 } 644 }
590 645
591
592 cdl.AddRow("Items", itemsOutput); 646 cdl.AddRow("Items", itemsOutput);
593 647
594 return sb.Append(cdl.ToString()); 648 return sb.Append(cdl.ToString());
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
index 7825e3e..b4348c9 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
@@ -35,11 +35,12 @@ using OpenSim.Framework;
35using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Scenes.Serialization; 36using OpenSim.Region.Framework.Scenes.Serialization;
37using OpenSim.Tests.Common; 37using OpenSim.Tests.Common;
38using OpenMetaverse.StructuredData;
38 39
39namespace OpenSim.Region.CoreModules.World.Serialiser.Tests 40namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
40{ 41{
41 [TestFixture] 42 [TestFixture]
42 public class SerialiserTests 43 public class SerialiserTests : OpenSimTestCase
43 { 44 {
44 private string xml = @" 45 private string xml = @"
45 <SceneObjectGroup> 46 <SceneObjectGroup>
@@ -143,6 +144,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
143 <Flags>None</Flags> 144 <Flags>None</Flags>
144 <CollisionSound><Guid>00000000-0000-0000-0000-000000000000</Guid></CollisionSound> 145 <CollisionSound><Guid>00000000-0000-0000-0000-000000000000</Guid></CollisionSound>
145 <CollisionSoundVolume>0</CollisionSoundVolume> 146 <CollisionSoundVolume>0</CollisionSoundVolume>
147 <DynAttrs><llsd><map><key>MyStore</key><map><key>the answer</key><integer>42</integer></map></map></llsd></DynAttrs>
146 </SceneObjectPart> 148 </SceneObjectPart>
147 </RootPart> 149 </RootPart>
148 <OtherParts /> 150 <OtherParts />
@@ -331,6 +333,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
331 <EveryoneMask>0</EveryoneMask> 333 <EveryoneMask>0</EveryoneMask>
332 <NextOwnerMask>2147483647</NextOwnerMask> 334 <NextOwnerMask>2147483647</NextOwnerMask>
333 <Flags>None</Flags> 335 <Flags>None</Flags>
336 <DynAttrs><llsd><map><key>MyStore</key><map><key>last words</key><string>Rosebud</string></map></map></llsd></DynAttrs>
334 <SitTargetAvatar><UUID>00000000-0000-0000-0000-000000000000</UUID></SitTargetAvatar> 337 <SitTargetAvatar><UUID>00000000-0000-0000-0000-000000000000</UUID></SitTargetAvatar>
335 </SceneObjectPart> 338 </SceneObjectPart>
336 <OtherParts /> 339 <OtherParts />
@@ -359,6 +362,8 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
359 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); 362 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790")));
360 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); 363 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d")));
361 Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide")); 364 Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide"));
365 OSDMap store = rootPart.DynAttrs["MyStore"];
366 Assert.AreEqual(42, store["the answer"].AsInteger());
362 367
363 // TODO: Check other properties 368 // TODO: Check other properties
364 } 369 }
@@ -409,6 +414,14 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
409 rp.CreatorID = rpCreatorId; 414 rp.CreatorID = rpCreatorId;
410 rp.Shape = shape; 415 rp.Shape = shape;
411 416
417 string daStoreName = "MyStore";
418 string daKey = "foo";
419 string daValue = "bar";
420 OSDMap myStore = new OSDMap();
421 myStore.Add(daKey, daValue);
422 rp.DynAttrs = new DAMap();
423 rp.DynAttrs[daStoreName] = myStore;
424
412 SceneObjectGroup so = new SceneObjectGroup(rp); 425 SceneObjectGroup so = new SceneObjectGroup(rp);
413 426
414 // Need to add the object to the scene so that the request to get script state succeeds 427 // Need to add the object to the scene so that the request to get script state succeeds
@@ -424,6 +437,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
424 UUID uuid = UUID.Zero; 437 UUID uuid = UUID.Zero;
425 string name = null; 438 string name = null;
426 UUID creatorId = UUID.Zero; 439 UUID creatorId = UUID.Zero;
440 DAMap daMap = null;
427 441
428 while (xtr.Read() && xtr.Name != "SceneObjectPart") 442 while (xtr.Read() && xtr.Name != "SceneObjectPart")
429 { 443 {
@@ -449,6 +463,10 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
449 creatorId = UUID.Parse(xtr.ReadElementString("UUID")); 463 creatorId = UUID.Parse(xtr.ReadElementString("UUID"));
450 xtr.ReadEndElement(); 464 xtr.ReadEndElement();
451 break; 465 break;
466 case "DynAttrs":
467 daMap = new DAMap();
468 daMap.ReadXml(xtr);
469 break;
452 } 470 }
453 } 471 }
454 472
@@ -462,6 +480,8 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
462 Assert.That(uuid, Is.EqualTo(rpUuid)); 480 Assert.That(uuid, Is.EqualTo(rpUuid));
463 Assert.That(name, Is.EqualTo(rpName)); 481 Assert.That(name, Is.EqualTo(rpName));
464 Assert.That(creatorId, Is.EqualTo(rpCreatorId)); 482 Assert.That(creatorId, Is.EqualTo(rpCreatorId));
483 Assert.NotNull(daMap);
484 Assert.AreEqual(daValue, daMap[daStoreName][daKey].AsString());
465 } 485 }
466 486
467 [Test] 487 [Test]
@@ -476,6 +496,8 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
476 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946"))); 496 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946")));
477 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef"))); 497 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef")));
478 Assert.That(rootPart.Name, Is.EqualTo("PrimFun")); 498 Assert.That(rootPart.Name, Is.EqualTo("PrimFun"));
499 OSDMap store = rootPart.DynAttrs["MyStore"];
500 Assert.AreEqual("Rosebud", store["last words"].AsString());
479 501
480 // TODO: Check other properties 502 // TODO: Check other properties
481 } 503 }
@@ -500,6 +522,14 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
500 rp.CreatorID = rpCreatorId; 522 rp.CreatorID = rpCreatorId;
501 rp.Shape = shape; 523 rp.Shape = shape;
502 524
525 string daStoreName = "MyStore";
526 string daKey = "foo";
527 string daValue = "bar";
528 OSDMap myStore = new OSDMap();
529 myStore.Add(daKey, daValue);
530 rp.DynAttrs = new DAMap();
531 rp.DynAttrs[daStoreName] = myStore;
532
503 SceneObjectGroup so = new SceneObjectGroup(rp); 533 SceneObjectGroup so = new SceneObjectGroup(rp);
504 534
505 // Need to add the object to the scene so that the request to get script state succeeds 535 // Need to add the object to the scene so that the request to get script state succeeds
@@ -516,6 +546,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
516 UUID uuid = UUID.Zero; 546 UUID uuid = UUID.Zero;
517 string name = null; 547 string name = null;
518 UUID creatorId = UUID.Zero; 548 UUID creatorId = UUID.Zero;
549 DAMap daMap = null;
519 550
520 while (xtr.Read() && xtr.Name != "SceneObjectPart") 551 while (xtr.Read() && xtr.Name != "SceneObjectPart")
521 { 552 {
@@ -537,6 +568,10 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
537 creatorId = UUID.Parse(xtr.ReadElementString("Guid")); 568 creatorId = UUID.Parse(xtr.ReadElementString("Guid"));
538 xtr.ReadEndElement(); 569 xtr.ReadEndElement();
539 break; 570 break;
571 case "DynAttrs":
572 daMap = new DAMap();
573 daMap.ReadXml(xtr);
574 break;
540 } 575 }
541 } 576 }
542 577
@@ -549,6 +584,8 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
549 Assert.That(uuid, Is.EqualTo(rpUuid)); 584 Assert.That(uuid, Is.EqualTo(rpUuid));
550 Assert.That(name, Is.EqualTo(rpName)); 585 Assert.That(name, Is.EqualTo(rpName));
551 Assert.That(creatorId, Is.EqualTo(rpCreatorId)); 586 Assert.That(creatorId, Is.EqualTo(rpCreatorId));
587 Assert.NotNull(daMap);
588 Assert.AreEqual(daValue, daMap[daStoreName][daKey].AsString());
552 } 589 }
553 } 590 }
554} \ No newline at end of file 591} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 513a8f5..883045a 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -43,8 +43,8 @@ namespace OpenSim.Region.CoreModules.World.Sound
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")]
44 public class SoundModule : INonSharedRegionModule, ISoundModule 44 public class SoundModule : INonSharedRegionModule, ISoundModule
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger( 46// private static readonly ILog m_log = LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType); 47// MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private Scene m_scene; 49 private Scene m_scene;
50 50
@@ -76,7 +76,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
76 76
77 public void RemoveRegion(Scene scene) 77 public void RemoveRegion(Scene scene)
78 { 78 {
79 m_scene.EventManager.OnClientLogin -= OnNewClient; 79 m_scene.EventManager.OnNewClient -= OnNewClient;
80 } 80 }
81 81
82 public void RegionLoaded(Scene scene) 82 public void RegionLoaded(Scene scene)
@@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
85 return; 85 return;
86 86
87 m_scene = scene; 87 m_scene = scene;
88 m_scene.EventManager.OnClientLogin += OnNewClient; 88 m_scene.EventManager.OnNewClient += OnNewClient;
89 89
90 m_scene.RegisterModuleInterface<ISoundModule>(this); 90 m_scene.RegisterModuleInterface<ISoundModule>(this);
91 } 91 }
diff --git a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
index a321c09..6f344c8 100644
--- a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
@@ -252,12 +252,11 @@ namespace OpenSim.Region.CoreModules
252 } 252 }
253 253
254 // TODO: Decouple this, so we can get rid of Linden Hour info 254 // TODO: Decouple this, so we can get rid of Linden Hour info
255 // Update Region infor with new Sun Position and Hour 255 // Update Region with new Sun Vector
256 // set estate settings for region access to sun position 256 // set estate settings for region access to sun position
257 if (receivedEstateToolsSunUpdate) 257 if (receivedEstateToolsSunUpdate)
258 { 258 {
259 m_scene.RegionInfo.RegionSettings.SunVector = Position; 259 m_scene.RegionInfo.RegionSettings.SunVector = Position;
260 m_scene.RegionInfo.RegionSettings.SunPosition = GetCurrentTimeAsLindenSunHour();
261 } 260 }
262 } 261 }
263 262
@@ -395,7 +394,7 @@ namespace OpenSim.Region.CoreModules
395 ready = false; 394 ready = false;
396 395
397 // Remove our hooks 396 // Remove our hooks
398 m_scene.EventManager.OnFrame -= SunUpdate; 397 m_scene.EventManager.OnFrame -= SunUpdate;
399 m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; 398 m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel;
400 m_scene.EventManager.OnEstateToolsSunUpdate -= EstateToolsSunUpdate; 399 m_scene.EventManager.OnEstateToolsSunUpdate -= EstateToolsSunUpdate;
401 m_scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour; 400 m_scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour;
@@ -459,26 +458,33 @@ namespace OpenSim.Region.CoreModules
459 SunToClient(avatar.ControllingClient); 458 SunToClient(avatar.ControllingClient);
460 } 459 }
461 460
462 /// <summary> 461 public void EstateToolsSunUpdate(ulong regionHandle)
463 ///
464 /// </summary>
465 /// <param name="regionHandle"></param>
466 /// <param name="FixedTime">Is the sun's position fixed?</param>
467 /// <param name="useEstateTime">Use the Region or Estate Sun hour?</param>
468 /// <param name="FixedSunHour">What hour of the day is the Sun Fixed at?</param>
469 public void EstateToolsSunUpdate(ulong regionHandle, bool FixedSun, bool useEstateTime, float FixedSunHour)
470 { 462 {
471 if (m_scene.RegionInfo.RegionHandle == regionHandle) 463 if (m_scene.RegionInfo.RegionHandle == regionHandle)
472 { 464 {
473 // Must limit the Sun Hour to 0 ... 24 465 float sunFixedHour;
474 while (FixedSunHour > 24.0f) 466 bool fixedSun;
475 FixedSunHour -= 24;
476 467
477 while (FixedSunHour < 0) 468 if (m_scene.RegionInfo.RegionSettings.UseEstateSun)
478 FixedSunHour += 24; 469 {
470 sunFixedHour = (float)m_scene.RegionInfo.EstateSettings.SunPosition;
471 fixedSun = m_scene.RegionInfo.EstateSettings.FixedSun;
472 }
473 else
474 {
475 sunFixedHour = (float)m_scene.RegionInfo.RegionSettings.SunPosition - 6.0f;
476 fixedSun = m_scene.RegionInfo.RegionSettings.FixedSun;
477 }
478
479 // Must limit the Sun Hour to 0 ... 24
480 while (sunFixedHour > 24.0f)
481 sunFixedHour -= 24;
479 482
480 m_SunFixedHour = FixedSunHour; 483 while (sunFixedHour < 0)
481 m_SunFixed = FixedSun; 484 sunFixedHour += 24;
485
486 m_SunFixedHour = sunFixedHour;
487 m_SunFixed = fixedSun;
482 488
483 // m_log.DebugFormat("[SUN]: Sun Settings Update: Fixed Sun? : {0}", m_SunFixed.ToString()); 489 // m_log.DebugFormat("[SUN]: Sun Settings Update: Fixed Sun? : {0}", m_SunFixed.ToString());
484 // m_log.DebugFormat("[SUN]: Sun Settings Update: Sun Hour : {0}", m_SunFixedHour.ToString()); 490 // m_log.DebugFormat("[SUN]: Sun Settings Update: Sun Hour : {0}", m_SunFixedHour.ToString());
@@ -501,7 +507,7 @@ namespace OpenSim.Region.CoreModules
501 { 507 {
502 m_scene.ForEachRootClient(delegate(IClientAPI client) 508 m_scene.ForEachRootClient(delegate(IClientAPI client)
503 { 509 {
504 SunToClient(client); 510 SunToClient(client);
505 }); 511 });
506 } 512 }
507 513
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 33aabe4..4d738a5 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -480,7 +480,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
480 else 480 else
481 { 481 {
482 m_plugineffects[pluginName] = effect; 482 m_plugineffects[pluginName] = effect;
483 m_log.Warn("E ... " + pluginName + " (Replaced)"); 483 m_log.Info("E ... " + pluginName + " (Replaced)");
484 } 484 }
485 } 485 }
486 } 486 }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
index 3d4f762..be719ea 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
@@ -30,11 +30,12 @@ using NUnit.Framework;
30using OpenSim.Framework; 30using OpenSim.Framework;
31using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; 31using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes;
32using OpenSim.Region.Framework.Scenes; 32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Tests.Common;
33 34
34namespace OpenSim.Region.CoreModules.World.Terrain.Tests 35namespace OpenSim.Region.CoreModules.World.Terrain.Tests
35{ 36{
36 [TestFixture] 37 [TestFixture]
37 public class TerrainTest 38 public class TerrainTest : OpenSimTestCase
38 { 39 {
39 [Test] 40 [Test]
40 public void BrushTest() 41 public void BrushTest()
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
index fd8e2b4..9de588c 100644
--- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules
66 public void Initialise(IConfigSource config) 66 public void Initialise(IConfigSource config)
67 { 67 {
68 m_windConfig = config.Configs["Wind"]; 68 m_windConfig = config.Configs["Wind"];
69 string desiredWindPlugin = m_dWindPluginName; 69// string desiredWindPlugin = m_dWindPluginName;
70 70
71 if (m_windConfig != null) 71 if (m_windConfig != null)
72 { 72 {
diff --git a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
index b926264..0f083c7 100644
--- a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index da39e95..cc7885a 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -35,8 +35,10 @@ namespace OpenSim.Region.Framework.Interfaces
35 35
36 public interface IJsonStoreModule 36 public interface IJsonStoreModule
37 { 37 {
38 bool AttachObjectStore(UUID objectID);
38 bool CreateStore(string value, ref UUID result); 39 bool CreateStore(string value, ref UUID result);
39 bool DestroyStore(UUID storeID); 40 bool DestroyStore(UUID storeID);
41 bool TestStore(UUID storeID);
40 bool TestPath(UUID storeID, string path, bool useJson); 42 bool TestPath(UUID storeID, string path, bool useJson);
41 bool SetValue(UUID storeID, string path, string value, bool useJson); 43 bool SetValue(UUID storeID, string path, string value, bool useJson);
42 bool RemoveValue(UUID storeID, string path); 44 bool RemoveValue(UUID storeID, string path);
diff --git a/OpenSim/Region/Framework/Scenes/Scripting/IScriptHost.cs b/OpenSim/Region/Framework/Interfaces/ISceneCommandsModule.cs
index f3be028..c5e678b 100644
--- a/OpenSim/Region/Framework/Scenes/Scripting/IScriptHost.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISceneCommandsModule.cs
@@ -9,7 +9,7 @@
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 OpenSim 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 *
@@ -25,22 +25,19 @@
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;
28using OpenMetaverse; 30using OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
29 33
30namespace OpenSim.Region.Framework.Scenes.Scripting 34namespace OpenSim.Region.Framework.Interfaces
31{ 35{
32 public interface IScriptHost 36 public interface ISceneCommandsModule
33 { 37 {
34 string Name { get; set; } 38 /// <summary>
35 string Description { get; set; } 39 /// Sets the scene debug options.
36 40 /// </summary>
37 UUID UUID { get; } 41 void SetSceneDebugOptions(Dictionary<string, string> options);
38 UUID OwnerID { get; }
39 UUID CreatorID { get; }
40 Vector3 AbsolutePosition { get; }
41
42 string SitName { get; set; }
43 string TouchName { get; set; }
44 void SetText(string text, Vector3 color, double alpha);
45 } 42 }
46} 43} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IXmlRpcRouter.cs b/OpenSim/Region/Framework/Interfaces/IXmlRpcRouter.cs
index 6db6674..093d3f0 100644
--- a/OpenSim/Region/Framework/Interfaces/IXmlRpcRouter.cs
+++ b/OpenSim/Region/Framework/Interfaces/IXmlRpcRouter.cs
@@ -34,5 +34,6 @@ namespace OpenSim.Region.Framework.Interfaces
34 void RegisterNewReceiver(IScriptModule scriptEngine, UUID channelID, UUID objectID, UUID itemID, string url); 34 void RegisterNewReceiver(IScriptModule scriptEngine, UUID channelID, UUID objectID, UUID itemID, string url);
35 void ScriptRemoved(UUID itemID); 35 void ScriptRemoved(UUID itemID);
36 void ObjectRemoved(UUID objectID); 36 void ObjectRemoved(UUID objectID);
37 void UnRegisterReceiver(string channelID, UUID itemID);
37 } 38 }
38} 39}
diff --git a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
index 9b504c0..2a5828e 100644
--- a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
index 65ae445..66edfed 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
@@ -87,13 +87,24 @@ namespace OpenSim.Region.Framework.Scenes.Animation
87 return false; 87 return false;
88 } 88 }
89 89
90 public bool Remove(UUID animID) 90 /// <summary>
91 /// Remove the specified animation
92 /// </summary>
93 /// <param name='animID'></param>
94 /// <param name='allowNoDefault'>
95 /// If true, then the default animation can be entirely removed.
96 /// If false, then removing the default animation will reset it to the simulator default (currently STAND).
97 /// </param>
98 public bool Remove(UUID animID, bool allowNoDefault)
91 { 99 {
92 lock (m_animations) 100 lock (m_animations)
93 { 101 {
94 if (m_defaultAnimation.AnimID == animID) 102 if (m_defaultAnimation.AnimID == animID)
95 { 103 {
96 m_defaultAnimation = new OpenSim.Framework.Animation(UUID.Zero, 1, UUID.Zero); 104 if (allowNoDefault)
105 m_defaultAnimation = new OpenSim.Framework.Animation(UUID.Zero, 1, UUID.Zero);
106 else
107 ResetDefaultAnimation();
97 } 108 }
98 else if (HasAnimation(animID)) 109 else if (HasAnimation(animID))
99 { 110 {
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 9458079..65c279e 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -26,9 +26,10 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Threading;
30using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using log4net; 33using log4net;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -86,6 +87,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
86 return; 87 return;
87 88
88 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name); 89 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name);
90 if (m_scenePresence.Scene.DebugAnimations)
91 m_log.DebugFormat(
92 "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}",
93 GetAnimName(animID), animID, m_scenePresence.Name);
89 94
90 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 95 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
91 SendAnimPack(); 96 SendAnimPack();
@@ -108,12 +113,25 @@ namespace OpenSim.Region.Framework.Scenes.Animation
108 AddAnimation(animID, objectID); 113 AddAnimation(animID, objectID);
109 } 114 }
110 115
111 public void RemoveAnimation(UUID animID) 116 /// <summary>
117 /// Remove the specified animation
118 /// </summary>
119 /// <param name='animID'></param>
120 /// <param name='allowNoDefault'>
121 /// If true, then the default animation can be entirely removed.
122 /// If false, then removing the default animation will reset it to the simulator default (currently STAND).
123 /// </param>
124 public void RemoveAnimation(UUID animID, bool allowNoDefault)
112 { 125 {
113 if (m_scenePresence.IsChildAgent) 126 if (m_scenePresence.IsChildAgent)
114 return; 127 return;
115 128
116 if (m_animations.Remove(animID)) 129 if (m_scenePresence.Scene.DebugAnimations)
130 m_log.DebugFormat(
131 "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}",
132 GetAnimName(animID), animID, m_scenePresence.Name);
133
134 if (m_animations.Remove(animID, allowNoDefault))
117 SendAnimPack(); 135 SendAnimPack();
118 } 136 }
119 137
@@ -127,7 +145,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
127 if (addRemove) 145 if (addRemove)
128 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero); 146 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero);
129 else 147 else
130 m_animations.Remove(animID); 148 m_animations.Remove(animID, true);
131 } 149 }
132 if(sendPack) 150 if(sendPack)
133 SendAnimPack(); 151 SendAnimPack();
@@ -145,14 +163,15 @@ namespace OpenSim.Region.Framework.Scenes.Animation
145 if (animID == UUID.Zero) 163 if (animID == UUID.Zero)
146 return; 164 return;
147 165
148 RemoveAnimation(animID); 166 RemoveAnimation(animID, true);
149 } 167 }
150 168
151 public void ResetAnimations() 169 public void ResetAnimations()
152 { 170 {
153// m_log.DebugFormat( 171 if (m_scenePresence.Scene.DebugAnimations)
154// "[SCENE PRESENCE ANIMATOR]: Resetting animations for {0} in {1}", 172 m_log.DebugFormat(
155// m_scenePresence.Name, m_scenePresence.Scene.RegionInfo.RegionName); 173 "[SCENE PRESENCE ANIMATOR]: Resetting animations for {0} in {1}",
174 m_scenePresence.Name, m_scenePresence.Scene.RegionInfo.RegionName);
156 175
157 m_animations.Clear(); 176 m_animations.Clear();
158 } 177 }
@@ -519,6 +538,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
519 if (m_scenePresence.IsChildAgent) 538 if (m_scenePresence.IsChildAgent)
520 return; 539 return;
521 540
541// m_log.DebugFormat(
542// "[SCENE PRESENCE ANIMATOR]: Sending anim pack with animations '{0}', sequence '{1}', uuids '{2}'",
543// string.Join(",", Array.ConvertAll<UUID, string>(animations, a => a.ToString())),
544// string.Join(",", Array.ConvertAll<int, string>(seqs, s => s.ToString())),
545// string.Join(",", Array.ConvertAll<UUID, string>(objectIDs, o => o.ToString())));
546
522 m_scenePresence.Scene.ForEachClient( 547 m_scenePresence.Scene.ForEachClient(
523 delegate(IClientAPI client) 548 delegate(IClientAPI client)
524 { 549 {
@@ -557,5 +582,21 @@ namespace OpenSim.Region.Framework.Scenes.Animation
557 582
558 SendAnimPack(animIDs, sequenceNums, objectIDs); 583 SendAnimPack(animIDs, sequenceNums, objectIDs);
559 } 584 }
585
586 public string GetAnimName(UUID animId)
587 {
588 string animName;
589
590 if (!DefaultAvatarAnimations.AnimsNames.TryGetValue(animId, out animName))
591 {
592 AssetMetadata amd = m_scenePresence.Scene.AssetService.GetMetadata(animId.ToString());
593 if (amd != null)
594 animName = amd.Name;
595 else
596 animName = "Unknown";
597 }
598
599 return animName;
600 }
560 } 601 }
561} 602}
diff --git a/OpenSim/Region/Framework/Scenes/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs
index b788a3c..7181313 100644
--- a/OpenSim/Region/Framework/Scenes/EntityManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using log4net; 32using log4net;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework;
34 35
35namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
36{ 37{
@@ -38,7 +39,8 @@ namespace OpenSim.Region.Framework.Scenes
38 { 39 {
39// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 41
41 private readonly DoubleDictionary<UUID, uint, EntityBase> m_entities = new DoubleDictionary<UUID, uint, EntityBase>(); 42 private readonly DoubleDictionaryThreadAbortSafe<UUID, uint, EntityBase> m_entities
43 = new DoubleDictionaryThreadAbortSafe<UUID, uint, EntityBase>();
42 44
43 public int Count 45 public int Count
44 { 46 {
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 5b1c9f4..052a05e 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -550,6 +550,20 @@ namespace OpenSim.Region.Framework.Scenes
550 /// </remarks> 550 /// </remarks>
551 public event ScriptControlEvent OnScriptControlEvent; 551 public event ScriptControlEvent OnScriptControlEvent;
552 552
553 public delegate void ScriptMovingStartEvent(uint localID);
554
555 /// <summary>
556 /// TODO: Should be triggered when a physics object starts moving.
557 /// </summary>
558 public event ScriptMovingStartEvent OnScriptMovingStartEvent;
559
560 public delegate void ScriptMovingEndEvent(uint localID);
561
562 /// <summary>
563 /// TODO: Should be triggered when a physics object stops moving.
564 /// </summary>
565 public event ScriptMovingEndEvent OnScriptMovingEndEvent;
566
553 public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); 567 public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos);
554 568
555 /// <summary> 569 /// <summary>
@@ -755,7 +769,7 @@ namespace OpenSim.Region.Framework.Scenes
755 public event ScriptTimerEvent OnScriptTimerEvent; 769 public event ScriptTimerEvent OnScriptTimerEvent;
756 */ 770 */
757 771
758 public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour); 772 public delegate void EstateToolsSunUpdate(ulong regionHandle);
759 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); 773 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID);
760 774
761 public event EstateToolsSunUpdate OnEstateToolsSunUpdate; 775 public event EstateToolsSunUpdate OnEstateToolsSunUpdate;
@@ -2238,6 +2252,48 @@ namespace OpenSim.Region.Framework.Scenes
2238 } 2252 }
2239 } 2253 }
2240 2254
2255 public void TriggerMovingStartEvent(uint localID)
2256 {
2257 ScriptMovingStartEvent handlerScriptMovingStartEvent = OnScriptMovingStartEvent;
2258 if (handlerScriptMovingStartEvent != null)
2259 {
2260 foreach (ScriptMovingStartEvent d in handlerScriptMovingStartEvent.GetInvocationList())
2261 {
2262 try
2263 {
2264 d(localID);
2265 }
2266 catch (Exception e)
2267 {
2268 m_log.ErrorFormat(
2269 "[EVENT MANAGER]: Delegate for TriggerMovingStartEvent failed - continuing. {0} {1}",
2270 e.Message, e.StackTrace);
2271 }
2272 }
2273 }
2274 }
2275
2276 public void TriggerMovingEndEvent(uint localID)
2277 {
2278 ScriptMovingEndEvent handlerScriptMovingEndEvent = OnScriptMovingEndEvent;
2279 if (handlerScriptMovingEndEvent != null)
2280 {
2281 foreach (ScriptMovingEndEvent d in handlerScriptMovingEndEvent.GetInvocationList())
2282 {
2283 try
2284 {
2285 d(localID);
2286 }
2287 catch (Exception e)
2288 {
2289 m_log.ErrorFormat(
2290 "[EVENT MANAGER]: Delegate for TriggerMovingEndEvent failed - continuing. {0} {1}",
2291 e.Message, e.StackTrace);
2292 }
2293 }
2294 }
2295 }
2296
2241 public void TriggerRequestChangeWaterHeight(float height) 2297 public void TriggerRequestChangeWaterHeight(float height)
2242 { 2298 {
2243 if (height < 0) 2299 if (height < 0)
@@ -2536,13 +2592,10 @@ namespace OpenSim.Region.Framework.Scenes
2536 } 2592 }
2537 2593
2538 /// <summary> 2594 /// <summary>
2539 /// Updates the system as to how the position of the sun should be handled. 2595 /// Called when the sun's position parameters have changed in the Region and/or Estate
2540 /// </summary> 2596 /// </summary>
2541 /// <param name="regionHandle"></param> 2597 /// <param name="regionHandle">The region that changed</param>
2542 /// <param name="FixedTime">True if the Sun Position is fixed</param> 2598 public void TriggerEstateToolsSunUpdate(ulong regionHandle)
2543 /// <param name="useEstateTime">True if the Estate Settings should be used instead of region</param>
2544 /// <param name="FixedSunHour">The hour 0.0 <= FixedSunHour <= 24.0 at which the sun is fixed at. Sun Hour 0 is sun-rise, when Day/Night ratio is 1:1</param>
2545 public void TriggerEstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool useEstateTime, float FixedSunHour)
2546 { 2599 {
2547 EstateToolsSunUpdate handlerEstateToolsSunUpdate = OnEstateToolsSunUpdate; 2600 EstateToolsSunUpdate handlerEstateToolsSunUpdate = OnEstateToolsSunUpdate;
2548 if (handlerEstateToolsSunUpdate != null) 2601 if (handlerEstateToolsSunUpdate != null)
@@ -2551,7 +2604,7 @@ namespace OpenSim.Region.Framework.Scenes
2551 { 2604 {
2552 try 2605 try
2553 { 2606 {
2554 d(regionHandle, FixedTime, useEstateTime, FixedSunHour); 2607 d(regionHandle);
2555 } 2608 }
2556 catch (Exception e) 2609 catch (Exception e)
2557 { 2610 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 4130029..a9e1fc2 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -684,12 +684,10 @@ namespace OpenSim.Region.Framework.Scenes
684 itemCopy.SalePrice = item.SalePrice; 684 itemCopy.SalePrice = item.SalePrice;
685 itemCopy.SaleType = item.SaleType; 685 itemCopy.SaleType = item.SaleType;
686 686
687 if (AddInventoryItem(itemCopy)) 687 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
688 { 688 if (invAccess != null)
689 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>(); 689 invAccess.TransferInventoryAssets(itemCopy, senderId, recipient);
690 if (invAccess != null) 690 AddInventoryItem(itemCopy);
691 Util.FireAndForget(delegate { invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); });
692 }
693 691
694 if (!Permissions.BypassPermissions()) 692 if (!Permissions.BypassPermissions())
695 { 693 {
@@ -1786,6 +1784,21 @@ namespace OpenSim.Region.Framework.Scenes
1786 /// <returns>The part where the script was rezzed if successful. False otherwise.</returns> 1784 /// <returns>The part where the script was rezzed if successful. False otherwise.</returns>
1787 public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase) 1785 public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase)
1788 { 1786 {
1787 return RezNewScript(
1788 agentID,
1789 itemBase,
1790 "default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}");
1791 }
1792
1793 /// <summary>
1794 /// Rez a new script from nothing with given script text.
1795 /// </summary>
1796 /// <param name="remoteClient"></param>
1797 /// <param name="itemBase">Template item.</param>
1798 /// <param name="scriptText"></param>
1799 /// <returns>The part where the script was rezzed if successful. False otherwise.</returns>
1800 public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase, string scriptText)
1801 {
1789 // The part ID is the folder ID! 1802 // The part ID is the folder ID!
1790 SceneObjectPart part = GetSceneObjectPart(itemBase.Folder); 1803 SceneObjectPart part = GetSceneObjectPart(itemBase.Folder);
1791 if (part == null) 1804 if (part == null)
@@ -1805,9 +1818,14 @@ namespace OpenSim.Region.Framework.Scenes
1805 return null; 1818 return null;
1806 } 1819 }
1807 1820
1808 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1821 AssetBase asset
1809 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"), 1822 = CreateAsset(
1810 agentID); 1823 itemBase.Name,
1824 itemBase.Description,
1825 (sbyte)itemBase.AssetType,
1826 Encoding.ASCII.GetBytes(scriptText),
1827 agentID);
1828
1811 AssetService.Store(asset); 1829 AssetService.Store(asset);
1812 1830
1813 TaskInventoryItem taskItem = new TaskInventoryItem(); 1831 TaskInventoryItem taskItem = new TaskInventoryItem();
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index e58aadc..c757147 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -68,14 +68,84 @@ namespace OpenSim.Region.Framework.Scenes
68 public bool EmergencyMonitoring = false; 68 public bool EmergencyMonitoring = false;
69 69
70 /// <summary> 70 /// <summary>
71 /// Show debug information about animations.
72 /// </summary>
73 public bool DebugAnimations { get; set; }
74
75 /// <summary>
71 /// Show debug information about teleports. 76 /// Show debug information about teleports.
72 /// </summary> 77 /// </summary>
73 public bool DebugTeleporting { get; private set; } 78 public bool DebugTeleporting { get; set; }
74 79
75 /// <summary> 80 /// <summary>
76 /// Show debug information about the scene loop. 81 /// Show debug information about the scene loop.
77 /// </summary> 82 /// </summary>
78 public bool DebugUpdates { get; private set; } 83 public bool DebugUpdates { get; set; }
84
85 /// <summary>
86 /// If true then the scene is saved to persistent storage periodically, every m_update_backup frames and
87 /// if objects meet required conditions (m_dontPersistBefore and m_dontPersistAfter).
88 /// </summary>
89 /// <remarks>
90 /// Even if false, the scene will still be saved on clean shutdown.
91 /// FIXME: Currently, setting this to false will mean that objects are not periodically returned from parcels.
92 /// This needs to be fixed.
93 /// </remarks>
94 public bool PeriodicBackup { get; set; }
95
96 /// <summary>
97 /// If false then the scene is never saved to persistence storage even if PeriodicBackup == true and even
98 /// if the scene is being shut down for the final time.
99 /// </summary>
100 public bool UseBackup { get; set; }
101
102 /// <summary>
103 /// If false then physical objects are disabled, though collisions will continue as normal.
104 /// </summary>
105 public bool PhysicsEnabled { get; set; }
106
107 /// <summary>
108 /// If false then scripts are not enabled on the smiulator
109 /// </summary>
110 public bool ScriptsEnabled
111 {
112 get { return m_scripts_enabled; }
113 set
114 {
115 if (m_scripts_enabled != value)
116 {
117 if (!value)
118 {
119 m_log.Info("Stopping all Scripts in Scene");
120
121 EntityBase[] entities = Entities.GetEntities();
122 foreach (EntityBase ent in entities)
123 {
124 if (ent is SceneObjectGroup)
125 ((SceneObjectGroup)ent).RemoveScriptInstances(false);
126 }
127 }
128 else
129 {
130 m_log.Info("Starting all Scripts in Scene");
131
132 EntityBase[] entities = Entities.GetEntities();
133 foreach (EntityBase ent in entities)
134 {
135 if (ent is SceneObjectGroup)
136 {
137 SceneObjectGroup sog = (SceneObjectGroup)ent;
138 sog.CreateScriptInstances(0, false, DefaultScriptEngine, 0);
139 sog.ResumeScripts();
140 }
141 }
142 }
143
144 m_scripts_enabled = value;
145 }
146 }
147 }
148 private bool m_scripts_enabled;
79 149
80 public SynchronizeSceneHandler SynchronizeScene; 150 public SynchronizeSceneHandler SynchronizeScene;
81 151
@@ -284,8 +354,6 @@ namespace OpenSim.Region.Framework.Scenes
284 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 354 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
285 private Dictionary<UUID, int> m_groupsWithTargets = new Dictionary<UUID, int>(); 355 private Dictionary<UUID, int> m_groupsWithTargets = new Dictionary<UUID, int>();
286 356
287 private bool m_physics_enabled = true;
288 private bool m_scripts_enabled = true;
289 private string m_defaultScriptEngine; 357 private string m_defaultScriptEngine;
290 358
291 /// <summary> 359 /// <summary>
@@ -348,7 +416,6 @@ namespace OpenSim.Region.Framework.Scenes
348 416
349 private Timer m_mapGenerationTimer = new Timer(); 417 private Timer m_mapGenerationTimer = new Timer();
350 private bool m_generateMaptiles; 418 private bool m_generateMaptiles;
351 private bool m_useBackup = true;
352 419
353 #endregion Fields 420 #endregion Fields
354 421
@@ -614,11 +681,6 @@ namespace OpenSim.Region.Framework.Scenes
614 get { return m_authenticateHandler; } 681 get { return m_authenticateHandler; }
615 } 682 }
616 683
617 public bool UseBackup
618 {
619 get { return m_useBackup; }
620 }
621
622 // an instance to the physics plugin's Scene object. 684 // an instance to the physics plugin's Scene object.
623 public PhysicsScene PhysicsScene 685 public PhysicsScene PhysicsScene
624 { 686 {
@@ -678,7 +740,6 @@ namespace OpenSim.Region.Framework.Scenes
678 public Scene(RegionInfo regInfo, AgentCircuitManager authen, 740 public Scene(RegionInfo regInfo, AgentCircuitManager authen,
679 SceneCommunicationService sceneGridService, 741 SceneCommunicationService sceneGridService,
680 ISimulationDataService simDataService, IEstateDataService estateDataService, 742 ISimulationDataService simDataService, IEstateDataService estateDataService,
681 bool dumpAssetsToFile,
682 IConfigSource config, string simulatorVersion) 743 IConfigSource config, string simulatorVersion)
683 : this(regInfo) 744 : this(regInfo)
684 { 745 {
@@ -762,15 +823,20 @@ namespace OpenSim.Region.Framework.Scenes
762 // 823 //
763 // Out of memory 824 // Out of memory
764 // Operating system has killed the plugin 825 // Operating system has killed the plugin
765 m_sceneGraph.UnRecoverableError += RestartNow; 826 m_sceneGraph.UnRecoverableError
827 += () =>
828 {
829 m_log.ErrorFormat("[SCENE]: Restarting region {0} due to unrecoverable physics crash", Name);
830 RestartNow();
831 };
766 832
767 RegisterDefaultSceneEvents(); 833 RegisterDefaultSceneEvents();
768 834
769 DumpAssetsToFile = dumpAssetsToFile; 835 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled
770 836 // better in the future.
771 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts; 837 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts;
772 838
773 m_physics_enabled = !RegionInfo.RegionSettings.DisablePhysics; 839 PhysicsEnabled = !RegionInfo.RegionSettings.DisablePhysics;
774 840
775 m_simulatorVersion = simulatorVersion + " (" + Util.GetRuntimeInformation() + ")"; 841 m_simulatorVersion = simulatorVersion + " (" + Util.GetRuntimeInformation() + ")";
776 842
@@ -778,141 +844,139 @@ namespace OpenSim.Region.Framework.Scenes
778 844
779 // Region config overrides global config 845 // Region config overrides global config
780 // 846 //
781 try 847 if (m_config.Configs["Startup"] != null)
782 { 848 {
783 if (m_config.Configs["Startup"] != null) 849 IConfig startupConfig = m_config.Configs["Startup"];
784 {
785 IConfig startupConfig = m_config.Configs["Startup"];
786 850
787 StartDisabled = startupConfig.GetBoolean("StartDisabled", false); 851 StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
788 852
789 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); 853 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
790 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); 854 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup);
791 if (!m_useBackup) 855 if (!UseBackup)
792 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 856 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
793 857
794 //Animation states 858 //Animation states
795 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 859 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
796 860
797 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 861 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
798 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 862 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
799 863
800 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 864 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
801 if (RegionInfo.NonphysPrimMin > 0) 865 if (RegionInfo.NonphysPrimMin > 0)
802 { 866 {
803 m_minNonphys = RegionInfo.NonphysPrimMin; 867 m_minNonphys = RegionInfo.NonphysPrimMin;
804 } 868 }
805 869
806 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 870 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
807 if (RegionInfo.NonphysPrimMax > 0) 871 if (RegionInfo.NonphysPrimMax > 0)
808 { 872 {
809 m_maxNonphys = RegionInfo.NonphysPrimMax; 873 m_maxNonphys = RegionInfo.NonphysPrimMax;
810 } 874 }
811 875
812 m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys); 876 m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys);
813 if (RegionInfo.PhysPrimMin > 0) 877 if (RegionInfo.PhysPrimMin > 0)
814 { 878 {
815 m_minPhys = RegionInfo.PhysPrimMin; 879 m_minPhys = RegionInfo.PhysPrimMin;
816 } 880 }
817 881
818 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 882 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
819 883
820 if (RegionInfo.PhysPrimMax > 0) 884 if (RegionInfo.PhysPrimMax > 0)
821 { 885 {
822 m_maxPhys = RegionInfo.PhysPrimMax; 886 m_maxPhys = RegionInfo.PhysPrimMax;
823 } 887 }
824 888
825 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); 889 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
826 if (RegionInfo.LinksetCapacity > 0) 890 if (RegionInfo.LinksetCapacity > 0)
827 { 891 {
828 m_linksetCapacity = RegionInfo.LinksetCapacity; 892 m_linksetCapacity = RegionInfo.LinksetCapacity;
829 } 893 }
830 894
831 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 895 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
832 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 896 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
833 897
834 // Here, if clamping is requested in either global or 898 // Here, if clamping is requested in either global or
835 // local config, it will be used 899 // local config, it will be used
836 // 900 //
837 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize); 901 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
838 if (RegionInfo.ClampPrimSize) 902 if (RegionInfo.ClampPrimSize)
903 {
904 m_clampPrimSize = true;
905 }
906
907 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
908 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
909 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
910 m_dontPersistBefore =
911 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
912 m_dontPersistBefore *= 10000000;
913 m_persistAfter =
914 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
915 m_persistAfter *= 10000000;
916
917 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
918 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
919
920 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
921 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
922 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
923
924 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
925 if (m_generateMaptiles)
926 {
927 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
928 if (maptileRefresh != 0)
839 { 929 {
840 m_clampPrimSize = true; 930 m_mapGenerationTimer.Interval = maptileRefresh * 1000;
931 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister;
932 m_mapGenerationTimer.AutoReset = true;
933 m_mapGenerationTimer.Start();
841 } 934 }
935 }
936 else
937 {
938 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
939 UUID tileID;
842 940
843 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete); 941 if (tile != UUID.Zero.ToString() && UUID.TryParse(tile, out tileID))
844 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
845 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
846 m_dontPersistBefore =
847 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
848 m_dontPersistBefore *= 10000000;
849 m_persistAfter =
850 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
851 m_persistAfter *= 10000000;
852
853 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
854 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
855
856 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
857 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
858 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
859
860 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
861 if (m_generateMaptiles)
862 { 942 {
863 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0); 943 RegionInfo.RegionSettings.TerrainImageID = tileID;
864 if (maptileRefresh != 0)
865 {
866 m_mapGenerationTimer.Interval = maptileRefresh * 1000;
867 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister;
868 m_mapGenerationTimer.AutoReset = true;
869 m_mapGenerationTimer.Start();
870 }
871 } 944 }
872 else 945 else
873 { 946 {
874 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString()); 947 RegionInfo.RegionSettings.TerrainImageID = RegionInfo.MaptileStaticUUID;
875 UUID tileID; 948 m_log.InfoFormat("[SCENE]: Region {0}, maptile set to {1}", RegionInfo.RegionName, RegionInfo.MaptileStaticUUID.ToString());
876
877 if (UUID.TryParse(tile, out tileID))
878 {
879 RegionInfo.RegionSettings.TerrainImageID = tileID;
880 }
881 } 949 }
950 }
882 951
883 string grant = startupConfig.GetString("AllowedClients", String.Empty); 952 string grant = startupConfig.GetString("AllowedClients", String.Empty);
884 if (grant.Length > 0) 953 if (grant.Length > 0)
954 {
955 foreach (string viewer in grant.Split(','))
885 { 956 {
886 foreach (string viewer in grant.Split(',')) 957 m_AllowedViewers.Add(viewer.Trim().ToLower());
887 {
888 m_AllowedViewers.Add(viewer.Trim().ToLower());
889 }
890 } 958 }
959 }
891 960
892 grant = startupConfig.GetString("BannedClients", String.Empty); 961 grant = startupConfig.GetString("BannedClients", String.Empty);
893 if (grant.Length > 0) 962 if (grant.Length > 0)
963 {
964 foreach (string viewer in grant.Split(','))
894 { 965 {
895 foreach (string viewer in grant.Split(',')) 966 m_BannedViewers.Add(viewer.Trim().ToLower());
896 {
897 m_BannedViewers.Add(viewer.Trim().ToLower());
898 }
899 } 967 }
900
901 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
902 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup);
903 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
904 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement);
905 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events);
906 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
907 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
908 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
909 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
910 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
911 } 968 }
912 } 969
913 catch (Exception e) 970 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
914 { 971 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup);
915 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString()); 972 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
973 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement);
974 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events);
975 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
976 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
977 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
978 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
979 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
916 } 980 }
917 981
918 // FIXME: Ultimately this should be in a module. 982 // FIXME: Ultimately this should be in a module.
@@ -965,6 +1029,10 @@ namespace OpenSim.Region.Framework.Scenes
965 { 1029 {
966 PhysicalPrims = true; 1030 PhysicalPrims = true;
967 CollidablePrims = true; 1031 CollidablePrims = true;
1032 PhysicsEnabled = true;
1033
1034 PeriodicBackup = true;
1035 UseBackup = true;
968 1036
969 BordersLocked = true; 1037 BordersLocked = true;
970 Border northBorder = new Border(); 1038 Border northBorder = new Border();
@@ -1207,83 +1275,6 @@ namespace OpenSim.Region.Framework.Scenes
1207 } 1275 }
1208 } 1276 }
1209 1277
1210 public void SetSceneCoreDebug(Dictionary<string, string> options)
1211 {
1212 if (options.ContainsKey("active"))
1213 {
1214 bool active;
1215
1216 if (bool.TryParse(options["active"], out active))
1217 Active = active;
1218 }
1219
1220 if (options.ContainsKey("scripting"))
1221 {
1222 bool enableScripts = true;
1223 if (bool.TryParse(options["scripting"], out enableScripts) && m_scripts_enabled != enableScripts)
1224 {
1225 if (!enableScripts)
1226 {
1227 m_log.Info("Stopping all Scripts in Scene");
1228
1229 EntityBase[] entities = Entities.GetEntities();
1230 foreach (EntityBase ent in entities)
1231 {
1232 if (ent is SceneObjectGroup)
1233 ((SceneObjectGroup)ent).RemoveScriptInstances(false);
1234 }
1235 }
1236 else
1237 {
1238 m_log.Info("Starting all Scripts in Scene");
1239
1240 EntityBase[] entities = Entities.GetEntities();
1241 foreach (EntityBase ent in entities)
1242 {
1243 if (ent is SceneObjectGroup)
1244 {
1245 SceneObjectGroup sog = (SceneObjectGroup)ent;
1246 sog.CreateScriptInstances(0, false, DefaultScriptEngine, 0);
1247 sog.ResumeScripts();
1248 }
1249 }
1250 }
1251
1252 m_scripts_enabled = enableScripts;
1253 }
1254 }
1255
1256 if (options.ContainsKey("physics"))
1257 {
1258 bool enablePhysics;
1259 if (bool.TryParse(options["physics"], out enablePhysics))
1260 m_physics_enabled = enablePhysics;
1261 }
1262
1263// if (options.ContainsKey("collisions"))
1264// {
1265// // TODO: Implement. If false, should stop objects colliding, though possibly should still allow
1266// // the avatar themselves to collide with the ground.
1267// }
1268
1269 if (options.ContainsKey("teleport"))
1270 {
1271 bool enableTeleportDebugging;
1272 if (bool.TryParse(options["teleport"], out enableTeleportDebugging))
1273 DebugTeleporting = enableTeleportDebugging;
1274 }
1275
1276 if (options.ContainsKey("updates"))
1277 {
1278 bool enableUpdateDebugging;
1279 if (bool.TryParse(options["updates"], out enableUpdateDebugging))
1280 {
1281 DebugUpdates = enableUpdateDebugging;
1282 GcNotify.Enabled = DebugUpdates;
1283 }
1284 }
1285 }
1286
1287 public int GetInaccurateNeighborCount() 1278 public int GetInaccurateNeighborCount()
1288 { 1279 {
1289 return m_neighbours.Count; 1280 return m_neighbours.Count;
@@ -1332,16 +1323,7 @@ namespace OpenSim.Region.Framework.Scenes
1332 1323
1333 m_log.Debug("[SCENE]: Persisting changed objects"); 1324 m_log.Debug("[SCENE]: Persisting changed objects");
1334 1325
1335 EntityBase[] entities = GetEntities(); 1326 Backup(false);
1336 foreach (EntityBase entity in entities)
1337 {
1338 if (!entity.IsDeleted && entity is SceneObjectGroup && ((SceneObjectGroup)entity).HasGroupChanged)
1339 {
1340 ((SceneObjectGroup)entity).ProcessBackup(SimulationDataService, false);
1341 }
1342 }
1343
1344 m_log.Debug("[SCENE]: Graph close");
1345 m_sceneGraph.Close(); 1327 m_sceneGraph.Close();
1346 1328
1347 if (!GridService.DeregisterRegion(RegionInfo.RegionID)) 1329 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
@@ -1568,7 +1550,7 @@ namespace OpenSim.Region.Framework.Scenes
1568 } 1550 }
1569 1551
1570 tmpMS = Util.EnvironmentTickCount(); 1552 tmpMS = Util.EnvironmentTickCount();
1571 if ((Frame % m_update_physics == 0) && m_physics_enabled) 1553 if (PhysicsEnabled && Frame % m_update_physics == 0)
1572 m_sceneGraph.UpdatePreparePhysics(); 1554 m_sceneGraph.UpdatePreparePhysics();
1573 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); 1555 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS);
1574 1556
@@ -1583,7 +1565,7 @@ namespace OpenSim.Region.Framework.Scenes
1583 tmpMS = Util.EnvironmentTickCount(); 1565 tmpMS = Util.EnvironmentTickCount();
1584 if (Frame % m_update_physics == 0) 1566 if (Frame % m_update_physics == 0)
1585 { 1567 {
1586 if (m_physics_enabled) 1568 if (PhysicsEnabled)
1587 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime); 1569 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime);
1588 1570
1589 if (SynchronizeScene != null) 1571 if (SynchronizeScene != null)
@@ -1625,7 +1607,7 @@ namespace OpenSim.Region.Framework.Scenes
1625 eventMS = Util.EnvironmentTickCountSubtract(tmpMS); 1607 eventMS = Util.EnvironmentTickCountSubtract(tmpMS);
1626 } 1608 }
1627 1609
1628 if (Frame % m_update_backup == 0) 1610 if (PeriodicBackup && Frame % m_update_backup == 0)
1629 { 1611 {
1630 tmpMS = Util.EnvironmentTickCount(); 1612 tmpMS = Util.EnvironmentTickCount();
1631 UpdateStorageBackup(); 1613 UpdateStorageBackup();
@@ -4709,19 +4691,6 @@ namespace OpenSim.Region.Framework.Scenes
4709 4691
4710 #region Script Engine 4692 #region Script Engine
4711 4693
4712 private List<ScriptEngineInterface> ScriptEngines = new List<ScriptEngineInterface>();
4713 public bool DumpAssetsToFile;
4714
4715 /// <summary>
4716 ///
4717 /// </summary>
4718 /// <param name="scriptEngine"></param>
4719 public void AddScriptEngine(ScriptEngineInterface scriptEngine)
4720 {
4721 ScriptEngines.Add(scriptEngine);
4722 scriptEngine.InitializeEngine(this);
4723 }
4724
4725 private bool ScriptDanger(SceneObjectPart part,Vector3 pos) 4694 private bool ScriptDanger(SceneObjectPart part,Vector3 pos)
4726 { 4695 {
4727 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); 4696 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y);
@@ -5628,33 +5597,7 @@ Environment.Exit(1);
5628 5597
5629 public void TriggerEstateSunUpdate() 5598 public void TriggerEstateSunUpdate()
5630 { 5599 {
5631 float sun; 5600 EventManager.TriggerEstateToolsSunUpdate(RegionInfo.RegionHandle);
5632 if (RegionInfo.RegionSettings.UseEstateSun)
5633 {
5634 sun = (float)RegionInfo.EstateSettings.SunPosition;
5635 if (RegionInfo.EstateSettings.UseGlobalTime)
5636 {
5637 sun = EventManager.GetCurrentTimeAsSunLindenHour() - 6.0f;
5638 }
5639
5640 //
5641 EventManager.TriggerEstateToolsSunUpdate(
5642 RegionInfo.RegionHandle,
5643 RegionInfo.EstateSettings.FixedSun,
5644 RegionInfo.RegionSettings.UseEstateSun,
5645 sun);
5646 }
5647 else
5648 {
5649 // Use the Sun Position from the Region Settings
5650 sun = (float)RegionInfo.RegionSettings.SunPosition - 6.0f;
5651
5652 EventManager.TriggerEstateToolsSunUpdate(
5653 RegionInfo.RegionHandle,
5654 RegionInfo.RegionSettings.FixedSun,
5655 RegionInfo.RegionSettings.UseEstateSun,
5656 sun);
5657 }
5658 } 5601 }
5659 5602
5660 private void HandleReloadEstate(string module, string[] cmd) 5603 private void HandleReloadEstate(string module, string[] cmd)
@@ -6050,10 +5993,17 @@ Environment.Exit(1);
6050 GC.Collect(); 5993 GC.Collect();
6051 } 5994 }
6052 5995
6053 // Wrappers to get physics modules retrieve assets. Has to be done this way 5996 /// <summary>
6054 // because we can't assign the asset service to physics directly - at the 5997 /// Wrappers to get physics modules retrieve assets.
6055 // time physics are instantiated it's not registered but it will be by 5998 /// </summary>
6056 // the time the first prim exists. 5999 /// <remarks>
6000 /// Has to be done this way
6001 /// because we can't assign the asset service to physics directly - at the
6002 /// time physics are instantiated it's not registered but it will be by
6003 /// the time the first prim exists.
6004 /// </remarks>
6005 /// <param name="assetID"></param>
6006 /// <param name="callback"></param>
6057 public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback) 6007 public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback)
6058 { 6008 {
6059 AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived); 6009 AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index ed1bbd8..0f5d116 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -101,6 +101,15 @@ namespace OpenSim.Region.Framework.Scenes
101 /// </summary> 101 /// </summary>
102 public partial class SceneObjectGroup : EntityBase, ISceneObject 102 public partial class SceneObjectGroup : EntityBase, ISceneObject
103 { 103 {
104 // Axis selection bitmask used by SetAxisRotation()
105 // Just happen to be the same bits used by llSetStatus() and defined in ScriptBaseClass.
106 public enum axisSelect : int
107 {
108 STATUS_ROTATE_X = 0x002,
109 STATUS_ROTATE_Y = 0x004,
110 STATUS_ROTATE_Z = 0x008,
111 }
112
104 // private PrimCountTaintedDelegate handlerPrimCountTainted = null; 113 // private PrimCountTaintedDelegate handlerPrimCountTainted = null;
105 114
106 /// <summary> 115 /// <summary>
@@ -512,11 +521,19 @@ namespace OpenSim.Region.Framework.Scenes
512 521
513 if (Scene != null) 522 if (Scene != null)
514 { 523 {
515 // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 524 if (
516 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 525 // (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E)
517 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 526 // || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
518 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W) 527 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N)
519 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S)) 528 // || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
529 // Experimental change for better border crossings.
530 // The commented out original lines above would, it seems, trigger
531 // a border crossing a little early or late depending on which
532 // direction the object was moving.
533 (Scene.TestBorderCross(val, Cardinals.E)
534 || Scene.TestBorderCross(val, Cardinals.W)
535 || Scene.TestBorderCross(val, Cardinals.N)
536 || Scene.TestBorderCross(val, Cardinals.S))
520 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 537 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
521 { 538 {
522 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 539 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
@@ -935,6 +952,18 @@ namespace OpenSim.Region.Framework.Scenes
935 /// </remarks> 952 /// </remarks>
936 public UUID FromFolderID { get; set; } 953 public UUID FromFolderID { get; set; }
937 954
955 /// <summary>
956 /// IDs of all avatars sat on this scene object.
957 /// </summary>
958 /// <remarks>
959 /// We need this so that we can maintain a linkset wide ordering of avatars sat on different parts.
960 /// This must be locked before it is read or written.
961 /// SceneObjectPart sitting avatar add/remove code also locks on this object to avoid race conditions.
962 /// No avatar should appear more than once in this list.
963 /// Do not manipulate this list directly - use the Add/Remove sitting avatar methods on SceneObjectPart.
964 /// </remarks>
965 protected internal List<UUID> m_sittingAvatars = new List<UUID>();
966
938 #endregion 967 #endregion
939 968
940// ~SceneObjectGroup() 969// ~SceneObjectGroup()
@@ -4509,17 +4538,28 @@ namespace OpenSim.Region.Framework.Scenes
4509 } 4538 }
4510 4539
4511 /// <summary> 4540 /// <summary>
4541 /// Get a copy of the list of sitting avatars on all prims of this object.
4542 /// </summary>
4543 /// <remarks>
4544 /// This is sorted by the order in which avatars sat down. If an avatar stands up then all avatars that sat
4545 /// down after it move one place down the list.
4546 /// </remarks>
4547 /// <returns>A list of the sitting avatars. Returns an empty list if there are no sitting avatars.</returns>
4548 public List<UUID> GetSittingAvatars()
4549 {
4550 lock (m_sittingAvatars)
4551 return new List<UUID>(m_sittingAvatars);
4552 }
4553
4554 /// <summary>
4512 /// Gets the number of sitting avatars. 4555 /// Gets the number of sitting avatars.
4513 /// </summary> 4556 /// </summary>
4514 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks> 4557 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
4515 /// <returns></returns> 4558 /// <returns></returns>
4516 public int GetSittingAvatarsCount() 4559 public int GetSittingAvatarsCount()
4517 { 4560 {
4518 int count = 0; 4561 lock (m_sittingAvatars)
4519 4562 return m_sittingAvatars.Count;
4520 Array.ForEach<SceneObjectPart>(m_parts.GetArray(), p => count += p.GetSittingAvatarsCount());
4521
4522 return count;
4523 } 4563 }
4524 4564
4525 public override string ToString() 4565 public override string ToString()
@@ -4528,7 +4568,7 @@ namespace OpenSim.Region.Framework.Scenes
4528 } 4568 }
4529 4569
4530 #region ISceneObject 4570 #region ISceneObject
4531 4571
4532 public virtual ISceneObject CloneForNewScene() 4572 public virtual ISceneObject CloneForNewScene()
4533 { 4573 {
4534 SceneObjectGroup sog = Copy(false); 4574 SceneObjectGroup sog = Copy(false);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 0d2da03..415a82b 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -37,6 +37,7 @@ using System.Xml.Serialization;
37using log4net; 37using log4net;
38using OpenMetaverse; 38using OpenMetaverse;
39using OpenMetaverse.Packets; 39using OpenMetaverse.Packets;
40using OpenMetaverse.StructuredData;
40using OpenSim.Framework; 41using OpenSim.Framework;
41using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes.Scripting; 43using OpenSim.Region.Framework.Scenes.Scripting;
@@ -116,7 +117,7 @@ namespace OpenSim.Region.Framework.Scenes
116 117
117 #endregion Enumerations 118 #endregion Enumerations
118 119
119 public class SceneObjectPart : IScriptHost, ISceneEntity 120 public class SceneObjectPart : ISceneEntity
120 { 121 {
121 /// <value> 122 /// <value>
122 /// Denote all sides of the prim 123 /// Denote all sides of the prim
@@ -136,6 +137,11 @@ namespace OpenSim.Region.Framework.Scenes
136 137
137 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 138 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
138 139
140 /// <summary>
141 /// Dynamic attributes can be created and deleted as required.
142 /// </summary>
143 public DAMap DynAttrs { get; set; }
144
139 /// <value> 145 /// <value>
140 /// Is this a root part? 146 /// Is this a root part?
141 /// </value> 147 /// </value>
@@ -386,6 +392,7 @@ namespace OpenSim.Region.Framework.Scenes
386 m_particleSystem = Utils.EmptyBytes; 392 m_particleSystem = Utils.EmptyBytes;
387 Rezzed = DateTime.UtcNow; 393 Rezzed = DateTime.UtcNow;
388 Description = String.Empty; 394 Description = String.Empty;
395 DynAttrs = new DAMap();
389 396
390 // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol, 397 // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol,
391 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 398 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
@@ -1342,7 +1349,7 @@ namespace OpenSim.Region.Framework.Scenes
1342 public UUID SitTargetAvatar { get; set; } 1349 public UUID SitTargetAvatar { get; set; }
1343 1350
1344 /// <summary> 1351 /// <summary>
1345 /// IDs of all avatars start on this object part. 1352 /// IDs of all avatars sat on this part.
1346 /// </summary> 1353 /// </summary>
1347 /// <remarks> 1354 /// <remarks>
1348 /// We need to track this so that we can stop sat upon prims from being attached. 1355 /// We need to track this so that we can stop sat upon prims from being attached.
@@ -2118,6 +2125,8 @@ namespace OpenSim.Region.Framework.Scenes
2118 // safeguard actual copy is done in sog.copy 2125 // safeguard actual copy is done in sog.copy
2119 dupe.KeyframeMotion = null; 2126 dupe.KeyframeMotion = null;
2120 2127
2128 dupe.DynAttrs.CopyFrom(DynAttrs);
2129
2121 if (userExposed) 2130 if (userExposed)
2122 { 2131 {
2123/* 2132/*
@@ -2431,11 +2440,11 @@ namespace OpenSim.Region.Framework.Scenes
2431 public int GetAxisRotation(int axis) 2440 public int GetAxisRotation(int axis)
2432 { 2441 {
2433 //Cannot use ScriptBaseClass constants as no referance to it currently. 2442 //Cannot use ScriptBaseClass constants as no referance to it currently.
2434 if (axis == 2)//STATUS_ROTATE_X 2443 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X)
2435 return STATUS_ROTATE_X; 2444 return STATUS_ROTATE_X;
2436 if (axis == 4)//STATUS_ROTATE_Y 2445 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y)
2437 return STATUS_ROTATE_Y; 2446 return STATUS_ROTATE_Y;
2438 if (axis == 8)//STATUS_ROTATE_Z 2447 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z)
2439 return STATUS_ROTATE_Z; 2448 return STATUS_ROTATE_Z;
2440 2449
2441 return 0; 2450 return 0;
@@ -2470,18 +2479,6 @@ namespace OpenSim.Region.Framework.Scenes
2470 return new Vector3(0, 0, 0); 2479 return new Vector3(0, 0, 0);
2471 2480
2472 return ParentGroup.GetGeometricCenter(); 2481 return ParentGroup.GetGeometricCenter();
2473
2474 /*
2475 PhysicsActor pa = PhysActor;
2476
2477 if (pa != null)
2478 {
2479 Vector3 vtmp = pa.CenterOfMass;
2480 return vtmp;
2481 }
2482 else
2483 return new Vector3(0, 0, 0);
2484 */
2485 } 2482 }
2486 2483
2487 public float GetMass() 2484 public float GetMass()
@@ -2895,11 +2892,14 @@ namespace OpenSim.Region.Framework.Scenes
2895 2892
2896 public void PhysicsOutOfBounds(Vector3 pos) 2893 public void PhysicsOutOfBounds(Vector3 pos)
2897 { 2894 {
2898 m_log.Error("[PHYSICS]: Physical Object went out of bounds."); 2895 // Note: This is only being called on the root prim at this time.
2896
2897 m_log.ErrorFormat(
2898 "[SCENE OBJECT PART]: Physical object {0}, localID {1} went out of bounds at {2} in {3}. Stopping at {4} and making non-physical.",
2899 Name, LocalId, pos, ParentGroup.Scene.Name, AbsolutePosition);
2899 2900
2900 RemFlag(PrimFlags.Physics); 2901 RemFlag(PrimFlags.Physics);
2901 DoPhysicsPropertyUpdate(false, true); 2902 DoPhysicsPropertyUpdate(false, true);
2902 //ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
2903 } 2903 }
2904 2904
2905 public void PhysicsRequestingTerseUpdate() 2905 public void PhysicsRequestingTerseUpdate()
@@ -3322,13 +3322,13 @@ namespace OpenSim.Region.Framework.Scenes
3322 ParentGroup.SetAxisRotation(axis, rotate); 3322 ParentGroup.SetAxisRotation(axis, rotate);
3323 3323
3324 //Cannot use ScriptBaseClass constants as no referance to it currently. 3324 //Cannot use ScriptBaseClass constants as no referance to it currently.
3325 if (axis == 2)//STATUS_ROTATE_X 3325 if ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
3326 STATUS_ROTATE_X = rotate; 3326 STATUS_ROTATE_X = rotate;
3327 3327
3328 if (axis == 4)//STATUS_ROTATE_Y 3328 if ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
3329 STATUS_ROTATE_Y = rotate; 3329 STATUS_ROTATE_Y = rotate;
3330 3330
3331 if (axis == 8)//STATUS_ROTATE_Z 3331 if ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
3332 STATUS_ROTATE_Z = rotate; 3332 STATUS_ROTATE_Z = rotate;
3333 } 3333 }
3334 3334
@@ -4235,6 +4235,7 @@ namespace OpenSim.Region.Framework.Scenes
4235 result.distance = distance2; 4235 result.distance = distance2;
4236 result.HitTF = true; 4236 result.HitTF = true;
4237 result.ipoint = q; 4237 result.ipoint = q;
4238 result.face = i;
4238 //m_log.Info("[FACE]:" + i.ToString()); 4239 //m_log.Info("[FACE]:" + i.ToString());
4239 //m_log.Info("[POINT]: " + q.ToString()); 4240 //m_log.Info("[POINT]: " + q.ToString());
4240 //m_log.Info("[DIST]: " + distance2.ToString()); 4241 //m_log.Info("[DIST]: " + distance2.ToString());
@@ -4558,7 +4559,7 @@ namespace OpenSim.Region.Framework.Scenes
4558 if (ParentGroup.RootPart == this) 4559 if (ParentGroup.RootPart == this)
4559 AngularVelocity = new Vector3(0, 0, 0); 4560 AngularVelocity = new Vector3(0, 0, 0);
4560 } 4561 }
4561 else 4562 else if (SetVD != wasVD)
4562 { 4563 {
4563 if (ParentGroup.Scene.CollidablePrims) 4564 if (ParentGroup.Scene.CollidablePrims)
4564 { 4565 {
@@ -4646,9 +4647,9 @@ namespace OpenSim.Region.Framework.Scenes
4646 PhysicsShapeType, 4647 PhysicsShapeType,
4647 m_localId); 4648 m_localId);
4648 } 4649 }
4649 catch (Exception ex) 4650 catch (Exception e)
4650 { 4651 {
4651 m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message); 4652 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
4652 pa = null; 4653 pa = null;
4653 } 4654 }
4654 4655
@@ -5202,18 +5203,22 @@ namespace OpenSim.Region.Framework.Scenes
5202 /// <param name='avatarId'></param> 5203 /// <param name='avatarId'></param>
5203 protected internal bool AddSittingAvatar(UUID avatarId) 5204 protected internal bool AddSittingAvatar(UUID avatarId)
5204 { 5205 {
5205 if (IsSitTargetSet && SitTargetAvatar == UUID.Zero) 5206 lock (ParentGroup.m_sittingAvatars)
5206 SitTargetAvatar = avatarId; 5207 {
5208 if (IsSitTargetSet && SitTargetAvatar == UUID.Zero)
5209 SitTargetAvatar = avatarId;
5207 5210
5208 HashSet<UUID> sittingAvatars = m_sittingAvatars; 5211 if (m_sittingAvatars == null)
5212 m_sittingAvatars = new HashSet<UUID>();
5209 5213
5210 if (sittingAvatars == null) 5214 if (m_sittingAvatars.Add(avatarId))
5211 sittingAvatars = new HashSet<UUID>(); 5215 {
5216 ParentGroup.m_sittingAvatars.Add(avatarId);
5212 5217
5213 lock (sittingAvatars) 5218 return true;
5214 { 5219 }
5215 m_sittingAvatars = sittingAvatars; 5220
5216 return m_sittingAvatars.Add(avatarId); 5221 return false;
5217 } 5222 }
5218 } 5223 }
5219 5224
@@ -5227,27 +5232,26 @@ namespace OpenSim.Region.Framework.Scenes
5227 /// <param name='avatarId'></param> 5232 /// <param name='avatarId'></param>
5228 protected internal bool RemoveSittingAvatar(UUID avatarId) 5233 protected internal bool RemoveSittingAvatar(UUID avatarId)
5229 { 5234 {
5230 if (SitTargetAvatar == avatarId) 5235 lock (ParentGroup.m_sittingAvatars)
5231 SitTargetAvatar = UUID.Zero; 5236 {
5232 5237 if (SitTargetAvatar == avatarId)
5233 HashSet<UUID> sittingAvatars = m_sittingAvatars; 5238 SitTargetAvatar = UUID.Zero;
5234 5239
5235 // This can occur under a race condition where another thread 5240 if (m_sittingAvatars == null)
5236 if (sittingAvatars == null) 5241 return false;
5237 return false;
5238 5242
5239 lock (sittingAvatars) 5243 if (m_sittingAvatars.Remove(avatarId))
5240 {
5241 if (sittingAvatars.Remove(avatarId))
5242 { 5244 {
5243 if (sittingAvatars.Count == 0) 5245 if (m_sittingAvatars.Count == 0)
5244 m_sittingAvatars = null; 5246 m_sittingAvatars = null;
5245 5247
5248 ParentGroup.m_sittingAvatars.Remove(avatarId);
5249
5246 return true; 5250 return true;
5247 } 5251 }
5248 }
5249 5252
5250 return false; 5253 return false;
5254 }
5251 } 5255 }
5252 5256
5253 /// <summary> 5257 /// <summary>
@@ -5257,16 +5261,12 @@ namespace OpenSim.Region.Framework.Scenes
5257 /// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns> 5261 /// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns>
5258 public HashSet<UUID> GetSittingAvatars() 5262 public HashSet<UUID> GetSittingAvatars()
5259 { 5263 {
5260 HashSet<UUID> sittingAvatars = m_sittingAvatars; 5264 lock (ParentGroup.m_sittingAvatars)
5261
5262 if (sittingAvatars == null)
5263 { 5265 {
5264 return null; 5266 if (m_sittingAvatars == null)
5265 } 5267 return null;
5266 else 5268 else
5267 { 5269 return new HashSet<UUID>(m_sittingAvatars);
5268 lock (sittingAvatars)
5269 return new HashSet<UUID>(sittingAvatars);
5270 } 5270 }
5271 } 5271 }
5272 5272
@@ -5277,13 +5277,13 @@ namespace OpenSim.Region.Framework.Scenes
5277 /// <returns></returns> 5277 /// <returns></returns>
5278 public int GetSittingAvatarsCount() 5278 public int GetSittingAvatarsCount()
5279 { 5279 {
5280 HashSet<UUID> sittingAvatars = m_sittingAvatars; 5280 lock (ParentGroup.m_sittingAvatars)
5281 5281 {
5282 if (sittingAvatars == null) 5282 if (m_sittingAvatars == null)
5283 return 0; 5283 return 0;
5284 5284 else
5285 lock (sittingAvatars) 5285 return m_sittingAvatars.Count;
5286 return sittingAvatars.Count; 5286 }
5287 } 5287 }
5288 } 5288 }
5289} 5289}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 91f9c0b..0bcf480 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -221,8 +221,6 @@ namespace OpenSim.Region.Framework.Scenes
221 221
222 private Quaternion m_headrotation = Quaternion.Identity; 222 private Quaternion m_headrotation = Quaternion.Identity;
223 223
224 private string m_nextSitAnimation = String.Empty;
225
226 //PauPaw:Proper PID Controler for autopilot************ 224 //PauPaw:Proper PID Controler for autopilot************
227 public bool MovingToTarget { get; private set; } 225 public bool MovingToTarget { get; private set; }
228 public Vector3 MoveToPositionTarget { get; private set; } 226 public Vector3 MoveToPositionTarget { get; private set; }
@@ -598,18 +596,18 @@ namespace OpenSim.Region.Framework.Scenes
598 set 596 set
599 { 597 {
600 m_bodyRot = value; 598 m_bodyRot = value;
601 // m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot);
602 if (PhysicsActor != null) 599 if (PhysicsActor != null)
603 { 600 {
604 try 601 try
605 { 602 {
606 PhysicsActor.Orientation = value; 603 PhysicsActor.Orientation = m_bodyRot;
607 } 604 }
608 catch (Exception e) 605 catch (Exception e)
609 { 606 {
610 m_log.Error("[SCENE PRESENCE]: Orientation " + e.Message); 607 m_log.Error("[SCENE PRESENCE]: Orientation " + e.Message);
611 } 608 }
612 } 609 }
610// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot);
613 } 611 }
614 } 612 }
615 613
@@ -2322,28 +2320,16 @@ namespace OpenSim.Region.Framework.Scenes
2322 2320
2323 if (ParentID != 0) 2321 if (ParentID != 0)
2324 { 2322 {
2323 if (ParentPart.UUID == targetID)
2324 return; // already sitting here, ignore
2325
2325 StandUp(); 2326 StandUp();
2326 } 2327 }
2327 2328
2328// if (!String.IsNullOrEmpty(sitAnimation))
2329// {
2330// m_nextSitAnimation = sitAnimation;
2331// }
2332// else
2333// {
2334 m_nextSitAnimation = "SIT";
2335// }
2336
2337 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
2338 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 2329 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
2339 2330
2340 if (part != null) 2331 if (part != null)
2341 { 2332 {
2342 if (!String.IsNullOrEmpty(part.SitAnimation))
2343 {
2344 m_nextSitAnimation = part.SitAnimation;
2345 }
2346
2347 m_requestedSitTargetID = part.LocalId; 2333 m_requestedSitTargetID = part.LocalId;
2348 m_requestedSitTargetUUID = targetID; 2334 m_requestedSitTargetUUID = targetID;
2349 2335
@@ -2464,18 +2450,6 @@ namespace OpenSim.Region.Framework.Scenes
2464 2450
2465 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 2451 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2466 { 2452 {
2467 if (!String.IsNullOrEmpty(m_nextSitAnimation))
2468 {
2469 HandleAgentSit(remoteClient, agentID, m_nextSitAnimation);
2470 }
2471 else
2472 {
2473 HandleAgentSit(remoteClient, agentID, "SIT");
2474 }
2475 }
2476
2477 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation)
2478 {
2479 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2453 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2480 2454
2481 if (part != null) 2455 if (part != null)
@@ -2545,10 +2519,15 @@ namespace OpenSim.Region.Framework.Scenes
2545 2519
2546 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2520 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2547 ParentID = m_requestedSitTargetID; 2521 ParentID = m_requestedSitTargetID;
2548 2522 m_AngularVelocity = Vector3.Zero;
2549 Velocity = Vector3.Zero; 2523 Velocity = Vector3.Zero;
2550 RemoveFromPhysicalScene(); 2524 RemoveFromPhysicalScene();
2551 2525
2526 String sitAnimation = "SIT";
2527 if (!String.IsNullOrEmpty(part.SitAnimation))
2528 {
2529 sitAnimation = part.SitAnimation;
2530 }
2552 Animator.TrySetMovementAnimation(sitAnimation); 2531 Animator.TrySetMovementAnimation(sitAnimation);
2553 SendAvatarDataToAllAgents(); 2532 SendAvatarDataToAllAgents();
2554 } 2533 }
@@ -2556,7 +2535,8 @@ namespace OpenSim.Region.Framework.Scenes
2556 2535
2557 public void HandleAgentSitOnGround() 2536 public void HandleAgentSitOnGround()
2558 { 2537 {
2559// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. 2538// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
2539 m_AngularVelocity = Vector3.Zero;
2560 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 2540 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
2561 SitGround = true; 2541 SitGround = true;
2562 RemoveFromPhysicalScene(); 2542 RemoveFromPhysicalScene();
@@ -2578,7 +2558,7 @@ namespace OpenSim.Region.Framework.Scenes
2578 2558
2579 public void HandleStopAnim(IClientAPI remoteClient, UUID animID) 2559 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
2580 { 2560 {
2581 Animator.RemoveAnimation(animID); 2561 Animator.RemoveAnimation(animID, false);
2582 } 2562 }
2583 2563
2584 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) 2564 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
diff --git a/OpenSim/Region/Framework/Scenes/Scripting/ScriptEngineLoader.cs b/OpenSim/Region/Framework/Scenes/Scripting/ScriptEngineLoader.cs
deleted file mode 100644
index c58ccc5..0000000
--- a/OpenSim/Region/Framework/Scenes/Scripting/ScriptEngineLoader.cs
+++ /dev/null
@@ -1,119 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/* Original code: Tedd Hansen */
29using System;
30using System.IO;
31using System.Reflection;
32using log4net;
33
34namespace OpenSim.Region.Framework.Scenes.Scripting
35{
36 public class ScriptEngineLoader
37 {
38 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
40 public ScriptEngineInterface LoadScriptEngine(string EngineName)
41 {
42 ScriptEngineInterface ret = null;
43 try
44 {
45 ret =
46 LoadAndInitAssembly(
47 Path.Combine("ScriptEngines", "OpenSim.Region.ScriptEngine." + EngineName + ".dll"),
48 "OpenSim.Region.ScriptEngine." + EngineName + ".ScriptEngine");
49 }
50 catch (Exception e)
51 {
52 m_log.Error("[ScriptEngine]: " +
53 "Error loading assembly \"" + EngineName + "\": " + e.Message + ", " +
54 e.StackTrace.ToString());
55 }
56 return ret;
57 }
58
59 /// <summary>
60 /// Does actual loading and initialization of script Assembly
61 /// </summary>
62 /// <param name="FreeAppDomain">AppDomain to load script into</param>
63 /// <param name="FileName">FileName of script assembly (.dll)</param>
64 /// <returns></returns>
65 private ScriptEngineInterface LoadAndInitAssembly(string FileName, string NameSpace)
66 {
67 //Common.SendToDebug("Loading ScriptEngine Assembly " + FileName);
68 // Load .Net Assembly (.dll)
69 // Initialize and return it
70
71 // TODO: Add error handling
72
73 Assembly a;
74 //try
75 //{
76
77
78 // Load to default appdomain (temporary)
79 a = Assembly.LoadFrom(FileName);
80 // Load to specified appdomain
81 // TODO: Insert security
82 //a = FreeAppDomain.Load(FileName);
83 //}
84 //catch (Exception e)
85 //{
86 // m_log.Error("[ScriptEngine]: Error loading assembly \String.Empty + FileName + "\": " + e.ToString());
87 //}
88
89
90 //m_log.Debug("Loading: " + FileName);
91 //foreach (Type _t in a.GetTypes())
92 //{
93 // m_log.Debug("Type: " + _t.ToString());
94 //}
95
96 Type t;
97 //try
98 //{
99 t = a.GetType(NameSpace, true);
100 //}
101 //catch (Exception e)
102 //{
103 // m_log.Error("[ScriptEngine]: Error initializing type \String.Empty + NameSpace + "\" from \String.Empty + FileName + "\": " + e.ToString());
104 //}
105
106 ScriptEngineInterface ret;
107 //try
108 //{
109 ret = (ScriptEngineInterface) Activator.CreateInstance(t);
110 //}
111 //catch (Exception e)
112 //{
113 // m_log.Error("[ScriptEngine]: Error initializing type \String.Empty + NameSpace + "\" from \String.Empty + FileName + "\": " + e.ToString());
114 //}
115
116 return ret;
117 }
118 }
119}
diff --git a/OpenSim/Region/Framework/Scenes/Scripting/ScriptUtils.cs b/OpenSim/Region/Framework/Scenes/Scripting/ScriptUtils.cs
new file mode 100644
index 0000000..f08ba59
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Scripting/ScriptUtils.cs
@@ -0,0 +1,107 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Region.Framework.Scenes.Scripting
34{
35 /// <summary>
36 /// Utility functions for use by scripts manipulating the scene.
37 /// </summary>
38 public static class ScriptUtils
39 {
40 /// <summary>
41 /// Get an asset id given an item name and an item type.
42 /// </summary>
43 /// <returns>UUID.Zero if the name and type did not match any item.</returns>
44 /// <param name='part'></param>
45 /// <param name='name'></param>
46 /// <param name='type'></param>
47 public static UUID GetAssetIdFromItemName(SceneObjectPart part, string name, int type)
48 {
49 TaskInventoryItem item = part.Inventory.GetInventoryItem(name);
50
51 if (item != null && item.Type == type)
52 return item.AssetID;
53 else
54 return UUID.Zero;
55 }
56
57 /// <summary>
58 /// accepts a valid UUID, -or- a name of an inventory item.
59 /// Returns a valid UUID or UUID.Zero if key invalid and item not found
60 /// in prim inventory.
61 /// </summary>
62 /// <param name="part">Scene object part to search for inventory item</param>
63 /// <param name="key"></param>
64 /// <returns></returns>
65 public static UUID GetAssetIdFromKeyOrItemName(SceneObjectPart part, string identifier)
66 {
67 UUID key;
68
69 // if we can parse the string as a key, use it.
70 // else try to locate the name in inventory of object. found returns key,
71 // not found returns UUID.Zero
72 if (!UUID.TryParse(identifier, out key))
73 {
74 TaskInventoryItem item = part.Inventory.GetInventoryItem(identifier);
75
76 if (item != null)
77 key = item.AssetID;
78 else
79 key = UUID.Zero;
80 }
81
82 return key;
83 }
84
85 /// <summary>
86 /// Return the UUID of the asset matching the specified key or name
87 /// and asset type.
88 /// </summary>
89 /// <param name="part">Scene object part to search for inventory item</param>
90 /// <param name="identifier"></param>
91 /// <param name="type"></param>
92 /// <returns></returns>
93 public static UUID GetAssetIdFromKeyOrItemName(SceneObjectPart part, string identifier, AssetType type)
94 {
95 UUID key;
96
97 if (!UUID.TryParse(identifier, out key))
98 {
99 TaskInventoryItem item = part.Inventory.GetInventoryItem(identifier);
100 if (item != null && item.Type == (int)type)
101 key = item.AssetID;
102 }
103
104 return key;
105 }
106 }
107} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 2984782..ce4fb40 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -365,6 +365,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
365 m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound); 365 m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound);
366 m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume); 366 m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume);
367 m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); 367 m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl);
368 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs);
368 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); 369 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation);
369 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); 370 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem);
370 m_SOPXmlProcessors.Add("PayPrice0", ProcessPayPrice0); 371 m_SOPXmlProcessors.Add("PayPrice0", ProcessPayPrice0);
@@ -797,6 +798,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
797 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); 798 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty);
798 } 799 }
799 800
801 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader)
802 {
803 obj.DynAttrs.ReadXml(reader);
804 }
805
800 private static void ProcessTextureAnimation(SceneObjectPart obj, XmlTextReader reader) 806 private static void ProcessTextureAnimation(SceneObjectPart obj, XmlTextReader reader)
801 { 807 {
802 obj.TextureAnimation = Convert.FromBase64String(reader.ReadElementContentAsString("TextureAnimation", String.Empty)); 808 obj.TextureAnimation = Convert.FromBase64String(reader.ReadElementContentAsString("TextureAnimation", String.Empty));
@@ -1339,6 +1345,14 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1339 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); 1345 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString());
1340 if (sop.MediaUrl != null) 1346 if (sop.MediaUrl != null)
1341 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); 1347 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
1348
1349 if (sop.DynAttrs.Count > 0)
1350 {
1351 writer.WriteStartElement("DynAttrs");
1352 sop.DynAttrs.WriteXml(writer);
1353 writer.WriteEndElement();
1354 }
1355
1342 WriteBytes(writer, "TextureAnimation", sop.TextureAnimation); 1356 WriteBytes(writer, "TextureAnimation", sop.TextureAnimation);
1343 WriteBytes(writer, "ParticleSystem", sop.ParticleSystem); 1357 WriteBytes(writer, "ParticleSystem", sop.ParticleSystem);
1344 writer.WriteElementString("PayPrice0", sop.PayPrice[0].ToString()); 1358 writer.WriteElementString("PayPrice0", sop.PayPrice[0].ToString());
diff --git a/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs b/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
index 4a21dc9..e209221 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
@@ -37,7 +37,7 @@ using OpenSim.Tests.Common;
37namespace OpenSim.Region.Framework.Scenes.Tests 37namespace OpenSim.Region.Framework.Scenes.Tests
38{ 38{
39 [TestFixture] 39 [TestFixture]
40 public class BorderTests 40 public class BorderTests : OpenSimTestCase
41 { 41 {
42 [Test] 42 [Test]
43 public void TestCross() 43 public void TestCross()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
index ea9fc93..766ce83 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
@@ -41,7 +41,7 @@ using OpenSim.Tests.Common;
41namespace OpenSim.Region.Framework.Scenes.Tests 41namespace OpenSim.Region.Framework.Scenes.Tests
42{ 42{
43 [TestFixture, LongRunning] 43 [TestFixture, LongRunning]
44 public class EntityManagerTests 44 public class EntityManagerTests : OpenSimTestCase
45 { 45 {
46 static public Random random; 46 static public Random random;
47 SceneObjectGroup found; 47 SceneObjectGroup found;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
index d23c965..575a081 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock;
40namespace OpenSim.Region.Framework.Scenes.Tests 40namespace OpenSim.Region.Framework.Scenes.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class SceneGraphTests 43 public class SceneGraphTests : OpenSimTestCase
44 { 44 {
45 [Test] 45 [Test]
46 public void TestDuplicateObject() 46 public void TestDuplicateObject()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs
index ab56f4e..2d831fa 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs
@@ -41,7 +41,7 @@ using OpenSim.Tests.Common.Mock;
41namespace OpenSim.Region.Framework.Scenes.Tests 41namespace OpenSim.Region.Framework.Scenes.Tests
42{ 42{
43 [TestFixture] 43 [TestFixture]
44 public class SceneManagerTests 44 public class SceneManagerTests : OpenSimTestCase
45 { 45 {
46 [Test] 46 [Test]
47 public void TestClose() 47 public void TestClose()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
index 5b334c6..a07d64c 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Threading; 31using System.Threading;
32using Nini.Config;
32using NUnit.Framework; 33using NUnit.Framework;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -182,6 +183,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
182 /// <summary> 183 /// <summary>
183 /// Test deleting an object from a scene. 184 /// Test deleting an object from a scene.
184 /// </summary> 185 /// </summary>
186 /// <remarks>
187 /// This is the most basic form of delete. For all more sophisticated forms of derez (done asynchrnously
188 /// and where object can be taken to user inventory, etc.), see SceneObjectDeRezTests.
189 /// </remarks>
185 [Test] 190 [Test]
186 public void TestDeleteSceneObject() 191 public void TestDeleteSceneObject()
187 { 192 {
@@ -201,100 +206,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
201 } 206 }
202 207
203 /// <summary> 208 /// <summary>
204 /// Test deleting an object asynchronously
205 /// </summary>
206 [Test]
207 public void TestDeleteSceneObjectAsync()
208 {
209 TestHelpers.InMethod();
210 //log4net.Config.XmlConfigurator.Configure();
211
212 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
213
214 TestScene scene = new SceneHelpers().SetupScene();
215
216 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
217 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
218 sogd.Enabled = false;
219
220 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
221
222 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
223 scene.DeRezObjects(client, new System.Collections.Generic.List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Delete, UUID.Zero);
224
225 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
226
227 Assert.That(retrievedPart, Is.Not.Null);
228
229 Assert.That(so.IsDeleted, Is.False);
230
231 sogd.InventoryDeQueueAndDelete();
232
233 Assert.That(so.IsDeleted, Is.True);
234
235 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
236 Assert.That(retrievedPart2, Is.Null);
237 }
238
239 /// <summary>
240 /// Test deleting an object asynchronously to user inventory.
241 /// </summary>
242// [Test]
243 public void TestDeleteSceneObjectAsyncToUserInventory()
244 {
245 TestHelpers.InMethod();
246 TestHelpers.EnableLogging();
247
248 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
249 string myObjectName = "Fred";
250
251 TestScene scene = new SceneHelpers().SetupScene();
252
253 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
254 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
255 sogd.Enabled = false;
256
257 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, myObjectName, agentId);
258
259// Assert.That(
260// scene.CommsManager.UserAdminService.AddUser(
261// "Bob", "Hoskins", "test", "test@test.com", 1000, 1000, agentId),
262// Is.EqualTo(agentId));
263
264 UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, agentId);
265 InventoryFolderBase folder1
266 = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, ua.PrincipalID, "folder1");
267
268 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
269 scene.DeRezObjects(client, new List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Take, folder1.ID);
270
271 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
272
273 Assert.That(retrievedPart, Is.Not.Null);
274 Assert.That(so.IsDeleted, Is.False);
275
276 sogd.InventoryDeQueueAndDelete();
277
278 Assert.That(so.IsDeleted, Is.True);
279
280 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
281 Assert.That(retrievedPart2, Is.Null);
282
283// SceneSetupHelpers.DeleteSceneObjectAsync(scene, part, DeRezAction.Take, userInfo.RootFolder.ID, client);
284
285 InventoryItemBase retrievedItem
286 = UserInventoryHelpers.GetInventoryItem(
287 scene.InventoryService, ua.PrincipalID, "folder1/" + myObjectName);
288
289 // Check that we now have the taken part in our inventory
290 Assert.That(retrievedItem, Is.Not.Null);
291
292 // Check that the taken part has actually disappeared
293// SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
294// Assert.That(retrievedPart, Is.Null);
295 }
296
297 /// <summary>
298 /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not 209 /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not
299 /// in a scene and is useful if one wants to supply a UUID directly rather than use the one generated by 210 /// in a scene and is useful if one wants to supply a UUID directly rather than use the one generated by
300 /// OpenSim. 211 /// OpenSim.
@@ -329,4 +240,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
329 Assert.That(sog.Parts.Length, Is.EqualTo(2)); 240 Assert.That(sog.Parts.Length, Is.EqualTo(2));
330 } 241 }
331 } 242 }
332} 243} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 0076f41..c1522e7 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -33,22 +33,24 @@ using NUnit.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Region.CoreModules.Framework.InventoryAccess;
36using OpenSim.Region.CoreModules.World.Permissions; 37using OpenSim.Region.CoreModules.World.Permissions;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces;
38using OpenSim.Tests.Common; 40using OpenSim.Tests.Common;
39using OpenSim.Tests.Common.Mock; 41using OpenSim.Tests.Common.Mock;
40 42
41namespace OpenSim.Region.Framework.Scenes.Tests 43namespace OpenSim.Region.Framework.Scenes.Tests
42{ 44{
43 /// <summary> 45 /// <summary>
44 /// Tests derez of scene objects by users. 46 /// Tests derez of scene objects.
45 /// </summary> 47 /// </summary>
46 /// <remarks> 48 /// <remarks>
47 /// This is at a level above the SceneObjectBasicTests, which act on the scene directly. 49 /// This is at a level above the SceneObjectBasicTests, which act on the scene directly.
48 /// TODO: These tests are very incomplete - they only test for a few conditions. 50 /// TODO: These tests are incomplete - need to test more kinds of derez (e.g. return object).
49 /// </remarks> 51 /// </remarks>
50 [TestFixture] 52 [TestFixture]
51 public class SceneObjectDeRezTests 53 public class SceneObjectDeRezTests : OpenSimTestCase
52 { 54 {
53 /// <summary> 55 /// <summary>
54 /// Test deleting an object from a scene. 56 /// Test deleting an object from a scene.
@@ -76,14 +78,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
76 = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); 78 = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero);
77 part.Name = "obj1"; 79 part.Name = "obj1";
78 scene.AddNewSceneObject(new SceneObjectGroup(part), false); 80 scene.AddNewSceneObject(new SceneObjectGroup(part), false);
81
79 List<uint> localIds = new List<uint>(); 82 List<uint> localIds = new List<uint>();
80 localIds.Add(part.LocalId); 83 localIds.Add(part.LocalId);
81
82 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); 84 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero);
85
86 // Check that object isn't deleted until we crank the sogd handle.
87 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
88 Assert.That(retrievedPart, Is.Not.Null);
89 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False);
90
83 sogd.InventoryDeQueueAndDelete(); 91 sogd.InventoryDeQueueAndDelete();
84 92
85 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 93 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId);
86 Assert.That(retrievedPart, Is.Null); 94 Assert.That(retrievedPart2, Is.Null);
87 } 95 }
88 96
89 /// <summary> 97 /// <summary>
@@ -124,6 +132,67 @@ namespace OpenSim.Region.Framework.Scenes.Tests
124 // Object should still be in the scene. 132 // Object should still be in the scene.
125 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 133 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
126 Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID)); 134 Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID));
127 } 135 }
136
137 /// <summary>
138 /// Test deleting an object asynchronously to user inventory.
139 /// </summary>
140 [Test]
141 public void TestDeleteSceneObjectAsyncToUserInventory()
142 {
143 TestHelpers.InMethod();
144// TestHelpers.EnableLogging();
145
146 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
147 string myObjectName = "Fred";
148
149 TestScene scene = new SceneHelpers().SetupScene();
150
151 IConfigSource configSource = new IniConfigSource();
152 IConfig config = configSource.AddConfig("Modules");
153 config.Set("InventoryAccessModule", "BasicInventoryAccessModule");
154 SceneHelpers.SetupSceneModules(
155 scene, configSource, new object[] { new BasicInventoryAccessModule() });
156
157 SceneHelpers.SetupSceneModules(scene, new object[] { });
158
159 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
160 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
161 sogd.Enabled = false;
162
163 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, myObjectName, agentId);
164
165 UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, agentId);
166 InventoryFolderBase folder1
167 = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, ua.PrincipalID, "folder1");
168
169 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
170 scene.DeRezObjects(client, new List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Take, folder1.ID);
171
172 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
173
174 Assert.That(retrievedPart, Is.Not.Null);
175 Assert.That(so.IsDeleted, Is.False);
176
177 sogd.InventoryDeQueueAndDelete();
178
179 Assert.That(so.IsDeleted, Is.True);
180
181 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
182 Assert.That(retrievedPart2, Is.Null);
183
184// SceneSetupHelpers.DeleteSceneObjectAsync(scene, part, DeRezAction.Take, userInfo.RootFolder.ID, client);
185
186 InventoryItemBase retrievedItem
187 = UserInventoryHelpers.GetInventoryItem(
188 scene.InventoryService, ua.PrincipalID, "folder1/" + myObjectName);
189
190 // Check that we now have the taken part in our inventory
191 Assert.That(retrievedItem, Is.Not.Null);
192
193 // Check that the taken part has actually disappeared
194// SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
195// Assert.That(retrievedPart, Is.Null);
196 }
128 } 197 }
129} \ No newline at end of file 198} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
index 0e525c9..9378e20 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
@@ -40,7 +40,7 @@ using log4net;
40namespace OpenSim.Region.Framework.Scenes.Tests 40namespace OpenSim.Region.Framework.Scenes.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class SceneObjectLinkingTests 43 public class SceneObjectLinkingTests : OpenSimTestCase
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
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
index e931859..1182c96 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
41 /// Basic scene object resize tests 41 /// Basic scene object resize tests
42 /// </summary> 42 /// </summary>
43 [TestFixture] 43 [TestFixture]
44 public class SceneObjectResizeTests 44 public class SceneObjectResizeTests : OpenSimTestCase
45 { 45 {
46 /// <summary> 46 /// <summary>
47 /// Test resizing an object 47 /// Test resizing an object
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
index d2361f8..a58e735 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock;
40namespace OpenSim.Region.Framework.Scenes.Tests 40namespace OpenSim.Region.Framework.Scenes.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class SceneObjectScriptTests 43 public class SceneObjectScriptTests : OpenSimTestCase
44 { 44 {
45 [Test] 45 [Test]
46 public void TestAddScript() 46 public void TestAddScript()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
index 6d255aa..abaa1d1 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
@@ -42,14 +42,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests
42 /// Spatial scene object tests (will eventually cover root and child part position, rotation properties, etc.) 42 /// Spatial scene object tests (will eventually cover root and child part position, rotation properties, etc.)
43 /// </summary> 43 /// </summary>
44 [TestFixture] 44 [TestFixture]
45 public class SceneObjectSpatialTests 45 public class SceneObjectSpatialTests : OpenSimTestCase
46 { 46 {
47 TestScene m_scene; 47 TestScene m_scene;
48 UUID m_ownerId = TestHelpers.ParseTail(0x1); 48 UUID m_ownerId = TestHelpers.ParseTail(0x1);
49 49
50 [SetUp] 50 [SetUp]
51 public void SetUp() 51 public override void SetUp()
52 { 52 {
53 base.SetUp();
54
53 m_scene = new SceneHelpers().SetupScene(); 55 m_scene = new SceneHelpers().SetupScene();
54 } 56 }
55 57
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
index 742c769..8eb3191 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
42 /// Basic scene object status tests 42 /// Basic scene object status tests
43 /// </summary> 43 /// </summary>
44 [TestFixture] 44 [TestFixture]
45 public class SceneObjectStatusTests 45 public class SceneObjectStatusTests : OpenSimTestCase
46 { 46 {
47 private TestScene m_scene; 47 private TestScene m_scene;
48 private UUID m_ownerId = TestHelpers.ParseTail(0x1); 48 private UUID m_ownerId = TestHelpers.ParseTail(0x1);
@@ -78,6 +78,26 @@ namespace OpenSim.Region.Framework.Scenes.Tests
78 } 78 }
79 79
80 [Test] 80 [Test]
81 public void TestSetNonPhysicsVolumeDetectSinglePrim()
82 {
83 TestHelpers.InMethod();
84
85 m_scene.AddSceneObject(m_so1);
86
87 SceneObjectPart rootPart = m_so1.RootPart;
88 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
89
90 m_so1.ScriptSetVolumeDetect(true);
91
92// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags);
93 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom));
94
95 m_so1.ScriptSetVolumeDetect(false);
96
97 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
98 }
99
100 [Test]
81 public void TestSetPhysicsSinglePrim() 101 public void TestSetPhysicsSinglePrim()
82 { 102 {
83 TestHelpers.InMethod(); 103 TestHelpers.InMethod();
@@ -89,13 +109,32 @@ namespace OpenSim.Region.Framework.Scenes.Tests
89 109
90 m_so1.ScriptSetPhysicsStatus(true); 110 m_so1.ScriptSetPhysicsStatus(true);
91 111
92// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags);
93 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics)); 112 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics));
94 113
95 m_so1.ScriptSetPhysicsStatus(false); 114 m_so1.ScriptSetPhysicsStatus(false);
96 115
97 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); 116 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
98 } 117 }
118
119 [Test]
120 public void TestSetPhysicsVolumeDetectSinglePrim()
121 {
122 TestHelpers.InMethod();
123
124 m_scene.AddSceneObject(m_so1);
125
126 SceneObjectPart rootPart = m_so1.RootPart;
127 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
128
129 m_so1.ScriptSetPhysicsStatus(true);
130 m_so1.ScriptSetVolumeDetect(true);
131
132 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.Physics));
133
134 m_so1.ScriptSetVolumeDetect(false);
135
136 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics));
137 }
99 138
100 [Test] 139 [Test]
101 public void TestSetPhysicsLinkset() 140 public void TestSetPhysicsLinkset()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
index 646e5fa..1cd8ae9 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
51 /// Scene presence animation tests 51 /// Scene presence animation tests
52 /// </summary> 52 /// </summary>
53 [TestFixture] 53 [TestFixture]
54 public class ScenePresenceAnimationTests 54 public class ScenePresenceAnimationTests : OpenSimTestCase
55 { 55 {
56 [Test] 56 [Test]
57 public void TestFlyingAnimation() 57 public void TestFlyingAnimation()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
index 1d1ff88..d80afd3 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
@@ -42,7 +42,7 @@ using OpenSim.Tests.Common.Mock;
42namespace OpenSim.Region.Framework.Scenes.Tests 42namespace OpenSim.Region.Framework.Scenes.Tests
43{ 43{
44 [TestFixture] 44 [TestFixture]
45 public class ScenePresenceAutopilotTests 45 public class ScenePresenceAutopilotTests : OpenSimTestCase
46 { 46 {
47 private TestScene m_scene; 47 private TestScene m_scene;
48 48
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index 493ab70..acaeb90 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -43,7 +43,7 @@ using System.Threading;
43namespace OpenSim.Region.Framework.Scenes.Tests 43namespace OpenSim.Region.Framework.Scenes.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class ScenePresenceSitTests 46 public class ScenePresenceSitTests : OpenSimTestCase
47 { 47 {
48 private TestScene m_scene; 48 private TestScene m_scene;
49 private ScenePresence m_sp; 49 private ScenePresence m_sp;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index 37b5184..8dd1f3d 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
49 /// Teleport tests in a standalone OpenSim 49 /// Teleport tests in a standalone OpenSim
50 /// </summary> 50 /// </summary>
51 [TestFixture] 51 [TestFixture]
52 public class ScenePresenceTeleportTests 52 public class ScenePresenceTeleportTests : OpenSimTestCase
53 { 53 {
54 [TestFixtureSetUp] 54 [TestFixtureSetUp]
55 public void FixtureInit() 55 public void FixtureInit()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
index ac3da1e..9d8eb0b 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
50 /// Scene presence tests 50 /// Scene presence tests
51 /// </summary> 51 /// </summary>
52 [TestFixture] 52 [TestFixture]
53 public class SceneTests 53 public class SceneTests : OpenSimTestCase
54 { 54 {
55 /// <summary> 55 /// <summary>
56 /// Very basic scene update test. Should become more elaborate with time. 56 /// Very basic scene update test. Should become more elaborate with time.
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
index a51e4e3..0b461f5 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -50,7 +50,7 @@ using OpenSim.Tests.Common.Mock;
50namespace OpenSim.Region.Framework.Tests 50namespace OpenSim.Region.Framework.Tests
51{ 51{
52 [TestFixture] 52 [TestFixture]
53 public class TaskInventoryTests 53 public class TaskInventoryTests : OpenSimTestCase
54 { 54 {
55 [Test] 55 [Test]
56 public void TestAddTaskInventoryItem() 56 public void TestAddTaskInventoryItem()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index 198e487..dd27294 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -38,7 +38,7 @@ using OpenSim.Tests.Common.Mock;
38namespace OpenSim.Region.Framework.Scenes.Tests 38namespace OpenSim.Region.Framework.Scenes.Tests
39{ 39{
40 [TestFixture] 40 [TestFixture]
41 public class UuidGathererTests 41 public class UuidGathererTests : OpenSimTestCase
42 { 42 {
43 protected IAssetService m_assetService; 43 protected IAssetService m_assetService;
44 protected UuidGatherer m_uuidGatherer; 44 protected UuidGatherer m_uuidGatherer;
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 2279e62..b09ae39 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -127,7 +127,10 @@ namespace OpenSim.Region.Framework.Scenes
127 /// within this object). 127 /// within this object).
128 /// </remarks> 128 /// </remarks>
129 /// <param name="sceneObject">The scene object for which to gather assets</param> 129 /// <param name="sceneObject">The scene object for which to gather assets</param>
130 /// <param name="assetUuids">The assets gathered</param> 130 /// <param name="assetUuids">
131 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset.
132 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown.
133 /// </param>
131 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) 134 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids)
132 { 135 {
133// m_log.DebugFormat( 136// m_log.DebugFormat(
@@ -257,8 +260,9 @@ namespace OpenSim.Region.Framework.Scenes
257 UUID uuid = new UUID(uuidMatch.Value); 260 UUID uuid = new UUID(uuidMatch.Value);
258// m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid); 261// m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid);
259 262
260 // Assume AssetIDs embedded are textures. 263 // Embedded asset references (if not false positives) could be for many types of asset, so we will
261 assetUuids[uuid] = AssetType.Texture; 264 // label these as unknown.
265 assetUuids[uuid] = AssetType.Unknown;
262 } 266 }
263 } 267 }
264 } 268 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs
new file mode 100644
index 0000000..84211a9
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs
@@ -0,0 +1,200 @@
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 System.Text;
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Framework.Console;
39using OpenSim.Framework.Monitoring;
40using OpenSim.Region.ClientStack.LindenUDP;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Scenes.Animation;
44using OpenSim.Services.Interfaces;
45
46namespace OpenSim.Region.OptionalModules.Avatar.Animations
47{
48 /// <summary>
49 /// A module that just holds commands for inspecting avatar animations.
50 /// </summary>
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AnimationsCommandModule")]
52 public class AnimationsCommandModule : ISharedRegionModule
53 {
54// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 private List<Scene> m_scenes = new List<Scene>();
57
58 public string Name { get { return "Animations Command Module"; } }
59
60 public Type ReplaceableInterface { get { return null; } }
61
62 public void Initialise(IConfigSource source)
63 {
64// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: INITIALIZED MODULE");
65 }
66
67 public void PostInitialise()
68 {
69// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: POST INITIALIZED MODULE");
70 }
71
72 public void Close()
73 {
74// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: CLOSED MODULE");
75 }
76
77 public void AddRegion(Scene scene)
78 {
79// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
80 }
81
82 public void RemoveRegion(Scene scene)
83 {
84// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
85
86 lock (m_scenes)
87 m_scenes.Remove(scene);
88 }
89
90 public void RegionLoaded(Scene scene)
91 {
92// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
93
94 lock (m_scenes)
95 m_scenes.Add(scene);
96
97 scene.AddCommand(
98 "Users", this, "show animations",
99 "show animations [<first-name> <last-name>]",
100 "Show animation information for avatars in this simulator.",
101 "If no name is supplied then information for all avatars is shown.\n"
102 + "Please note that for inventory animations, the animation name is the name under which the animation was originally uploaded\n"
103 + ", which is not necessarily the current inventory name.",
104 HandleShowAnimationsCommand);
105 }
106
107 protected void HandleShowAnimationsCommand(string module, string[] cmd)
108 {
109 if (cmd.Length != 2 && cmd.Length < 4)
110 {
111 MainConsole.Instance.OutputFormat("Usage: show animations [<first-name> <last-name>]");
112 return;
113 }
114
115 bool targetNameSupplied = false;
116 string optionalTargetFirstName = null;
117 string optionalTargetLastName = null;
118
119 if (cmd.Length >= 4)
120 {
121 targetNameSupplied = true;
122 optionalTargetFirstName = cmd[2];
123 optionalTargetLastName = cmd[3];
124 }
125
126 StringBuilder sb = new StringBuilder();
127
128 lock (m_scenes)
129 {
130 foreach (Scene scene in m_scenes)
131 {
132 if (targetNameSupplied)
133 {
134 ScenePresence sp = scene.GetScenePresence(optionalTargetFirstName, optionalTargetLastName);
135 if (sp != null && !sp.IsChildAgent)
136 GetAttachmentsReport(sp, sb);
137 }
138 else
139 {
140 scene.ForEachRootScenePresence(sp => GetAttachmentsReport(sp, sb));
141 }
142 }
143 }
144
145 MainConsole.Instance.Output(sb.ToString());
146 }
147
148 private void GetAttachmentsReport(ScenePresence sp, StringBuilder sb)
149 {
150 sb.AppendFormat("Animations for {0}\n", sp.Name);
151
152 ConsoleDisplayList cdl = new ConsoleDisplayList() { Indent = 2 };
153 ScenePresenceAnimator spa = sp.Animator;
154 AnimationSet anims = sp.Animator.Animations;
155
156 string cma = spa.CurrentMovementAnimation;
157 cdl.AddRow(
158 "Current movement anim",
159 string.Format("{0}, {1}", DefaultAvatarAnimations.GetDefaultAnimation(cma), cma));
160
161 UUID defaultAnimId = anims.DefaultAnimation.AnimID;
162 cdl.AddRow(
163 "Default anim",
164 string.Format("{0}, {1}", defaultAnimId, sp.Animator.GetAnimName(defaultAnimId)));
165
166 UUID implicitDefaultAnimId = anims.ImplicitDefaultAnimation.AnimID;
167 cdl.AddRow(
168 "Implicit default anim",
169 string.Format("{0}, {1}",
170 implicitDefaultAnimId, sp.Animator.GetAnimName(implicitDefaultAnimId)));
171
172 cdl.AddToStringBuilder(sb);
173
174 ConsoleDisplayTable cdt = new ConsoleDisplayTable() { Indent = 2 };
175 cdt.AddColumn("Animation ID", 36);
176 cdt.AddColumn("Name", 20);
177 cdt.AddColumn("Seq", 3);
178 cdt.AddColumn("Object ID", 36);
179
180 UUID[] animIds;
181 int[] sequenceNumbers;
182 UUID[] objectIds;
183
184 sp.Animator.Animations.GetArrays(out animIds, out sequenceNumbers, out objectIds);
185
186 for (int i = 0; i < animIds.Length; i++)
187 {
188 UUID animId = animIds[i];
189 string animName = sp.Animator.GetAnimName(animId);
190 int seq = sequenceNumbers[i];
191 UUID objectId = objectIds[i];
192
193 cdt.AddRow(animId, animName, seq, objectId);
194 }
195
196 cdt.AddToStringBuilder(sb);
197 sb.Append("\n");
198 }
199 }
200} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
index 68bcb4a..d97e3b3 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
@@ -97,6 +97,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
97 "Users", this, "attachments show", 97 "Users", this, "attachments show",
98 "attachments show [<first-name> <last-name>]", 98 "attachments show [<first-name> <last-name>]",
99 "Show attachment information for avatars in this simulator.", 99 "Show attachment information for avatars in this simulator.",
100 "If no name is supplied then information for all avatars is shown.",
100 HandleShowAttachmentsCommand); 101 HandleShowAttachmentsCommand);
101 } 102 }
102 103
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
index 66265d8..5a37fad 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
@@ -55,42 +55,42 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
55 // These are the IRC Connector configurable parameters with hard-wired 55 // These are the IRC Connector configurable parameters with hard-wired
56 // default values (retained for compatability). 56 // default values (retained for compatability).
57 57
58 internal string Server = null; 58 internal string Server = null;
59 internal string Password = null; 59 internal string Password = null;
60 internal string IrcChannel = null; 60 internal string IrcChannel = null;
61 internal string BaseNickname = "OSimBot"; 61 internal string BaseNickname = "OSimBot";
62 internal uint Port = 6667; 62 internal uint Port = 6667;
63 internal string User = null; 63 internal string User = null;
64 64
65 internal bool ClientReporting = true; 65 internal bool ClientReporting = true;
66 internal bool RelayChat = true; 66 internal bool RelayChat = true;
67 internal bool RelayPrivateChannels = false; 67 internal bool RelayPrivateChannels = false;
68 internal int RelayChannel = 1; 68 internal int RelayChannel = 1;
69 internal List<int> ValidInWorldChannels = new List<int>(); 69 internal List<int> ValidInWorldChannels = new List<int>();
70 70
71 // Connector agnostic parameters. These values are NOT shared with the 71 // Connector agnostic parameters. These values are NOT shared with the
72 // connector and do not differentiate at an IRC level 72 // connector and do not differentiate at an IRC level
73 73
74 internal string PrivateMessageFormat = "PRIVMSG {0} :<{2}> {1} {3}"; 74 internal string PrivateMessageFormat = "PRIVMSG {0} :<{2}> {1} {3}";
75 internal string NoticeMessageFormat = "PRIVMSG {0} :<{2}> {3}"; 75 internal string NoticeMessageFormat = "PRIVMSG {0} :<{2}> {3}";
76 internal int RelayChannelOut = -1; 76 internal int RelayChannelOut = -1;
77 internal bool RandomizeNickname = true; 77 internal bool RandomizeNickname = true;
78 internal bool CommandsEnabled = false; 78 internal bool CommandsEnabled = false;
79 internal int CommandChannel = -1; 79 internal int CommandChannel = -1;
80 internal int ConnectDelay = 10; 80 internal int ConnectDelay = 10;
81 internal int PingDelay = 15; 81 internal int PingDelay = 15;
82 internal string DefaultZone = "Sim"; 82 internal string DefaultZone = "Sim";
83 83
84 internal string _accessPassword = String.Empty; 84 internal string _accessPassword = String.Empty;
85 internal Regex AccessPasswordRegex = null; 85 internal Regex AccessPasswordRegex = null;
86 internal List<string> ExcludeList = new List<string>(); 86 internal List<string> ExcludeList = new List<string>();
87 internal string AccessPassword 87 internal string AccessPassword
88 { 88 {
89 get { return _accessPassword; } 89 get { return _accessPassword; }
90 set 90 set
91 { 91 {
92 _accessPassword = value; 92 _accessPassword = value;
93 AccessPasswordRegex = new Regex(String.Format(@"^{0},\s*(?<avatar>[^,]+),\s*(?<message>.+)$", _accessPassword), 93 AccessPasswordRegex = new Regex(String.Format(@"^{0},\s*(?<avatar>[^,]+),\s*(?<message>.+)$", _accessPassword),
94 RegexOptions.Compiled); 94 RegexOptions.Compiled);
95 } 95 }
96 } 96 }
@@ -99,9 +99,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
99 99
100 // IRC connector reference 100 // IRC connector reference
101 101
102 internal IRCConnector irc = null; 102 internal IRCConnector irc = null;
103 103
104 internal int idn = _idk_++; 104 internal int idn = _idk_++;
105 105
106 // List of regions dependent upon this connection 106 // List of regions dependent upon this connection
107 107
@@ -119,29 +119,29 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
119 119
120 internal ChannelState(ChannelState model) 120 internal ChannelState(ChannelState model)
121 { 121 {
122 Server = model.Server; 122 Server = model.Server;
123 Password = model.Password; 123 Password = model.Password;
124 IrcChannel = model.IrcChannel; 124 IrcChannel = model.IrcChannel;
125 Port = model.Port; 125 Port = model.Port;
126 BaseNickname = model.BaseNickname; 126 BaseNickname = model.BaseNickname;
127 RandomizeNickname = model.RandomizeNickname; 127 RandomizeNickname = model.RandomizeNickname;
128 User = model.User; 128 User = model.User;
129 CommandsEnabled = model.CommandsEnabled; 129 CommandsEnabled = model.CommandsEnabled;
130 CommandChannel = model.CommandChannel; 130 CommandChannel = model.CommandChannel;
131 RelayChat = model.RelayChat; 131 RelayChat = model.RelayChat;
132 RelayPrivateChannels = model.RelayPrivateChannels; 132 RelayPrivateChannels = model.RelayPrivateChannels;
133 RelayChannelOut = model.RelayChannelOut; 133 RelayChannelOut = model.RelayChannelOut;
134 RelayChannel = model.RelayChannel; 134 RelayChannel = model.RelayChannel;
135 ValidInWorldChannels = model.ValidInWorldChannels; 135 ValidInWorldChannels = model.ValidInWorldChannels;
136 PrivateMessageFormat = model.PrivateMessageFormat; 136 PrivateMessageFormat = model.PrivateMessageFormat;
137 NoticeMessageFormat = model.NoticeMessageFormat; 137 NoticeMessageFormat = model.NoticeMessageFormat;
138 ClientReporting = model.ClientReporting; 138 ClientReporting = model.ClientReporting;
139 AccessPassword = model.AccessPassword; 139 AccessPassword = model.AccessPassword;
140 DefaultZone = model.DefaultZone; 140 DefaultZone = model.DefaultZone;
141 ConnectDelay = model.ConnectDelay; 141 ConnectDelay = model.ConnectDelay;
142 PingDelay = model.PingDelay; 142 PingDelay = model.PingDelay;
143 } 143 }
144 144
145 // Read the configuration file, performing variable substitution and any 145 // Read the configuration file, performing variable substitution and any
146 // necessary aliasing. See accompanying documentation for how this works. 146 // necessary aliasing. See accompanying documentation for how this works.
147 // If you don't need variables, then this works exactly as before. 147 // If you don't need variables, then this works exactly as before.
@@ -160,54 +160,54 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
160 160
161 m_log.DebugFormat("[IRC-Channel-{0}] Initial request by Region {1} to connect to IRC", cs.idn, rs.Region); 161 m_log.DebugFormat("[IRC-Channel-{0}] Initial request by Region {1} to connect to IRC", cs.idn, rs.Region);
162 162
163 cs.Server = Substitute(rs, config.GetString("server", null)); 163 cs.Server = Substitute(rs, config.GetString("server", null));
164 m_log.DebugFormat("[IRC-Channel-{0}] Server : <{1}>", cs.idn, cs.Server); 164 m_log.DebugFormat("[IRC-Channel-{0}] Server : <{1}>", cs.idn, cs.Server);
165 cs.Password = Substitute(rs, config.GetString("password", null)); 165 cs.Password = Substitute(rs, config.GetString("password", null));
166 // probably not a good idea to put a password in the log file 166 // probably not a good idea to put a password in the log file
167 cs.User = Substitute(rs, config.GetString("user", null)); 167 cs.User = Substitute(rs, config.GetString("user", null));
168 cs.IrcChannel = Substitute(rs, config.GetString("channel", null)); 168 cs.IrcChannel = Substitute(rs, config.GetString("channel", null));
169 m_log.DebugFormat("[IRC-Channel-{0}] IrcChannel : <{1}>", cs.idn, cs.IrcChannel); 169 m_log.DebugFormat("[IRC-Channel-{0}] IrcChannel : <{1}>", cs.idn, cs.IrcChannel);
170 cs.Port = Convert.ToUInt32(Substitute(rs, config.GetString("port", Convert.ToString(cs.Port)))); 170 cs.Port = Convert.ToUInt32(Substitute(rs, config.GetString("port", Convert.ToString(cs.Port))));
171 m_log.DebugFormat("[IRC-Channel-{0}] Port : <{1}>", cs.idn, cs.Port); 171 m_log.DebugFormat("[IRC-Channel-{0}] Port : <{1}>", cs.idn, cs.Port);
172 cs.BaseNickname = Substitute(rs, config.GetString("nick", cs.BaseNickname)); 172 cs.BaseNickname = Substitute(rs, config.GetString("nick", cs.BaseNickname));
173 m_log.DebugFormat("[IRC-Channel-{0}] BaseNickname : <{1}>", cs.idn, cs.BaseNickname); 173 m_log.DebugFormat("[IRC-Channel-{0}] BaseNickname : <{1}>", cs.idn, cs.BaseNickname);
174 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("randomize_nick", Convert.ToString(cs.RandomizeNickname)))); 174 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("randomize_nick", Convert.ToString(cs.RandomizeNickname))));
175 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname); 175 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
176 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("nicknum", Convert.ToString(cs.RandomizeNickname)))); 176 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("nicknum", Convert.ToString(cs.RandomizeNickname))));
177 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname); 177 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
178 cs.User = Substitute(rs, config.GetString("username", cs.User)); 178 cs.User = Substitute(rs, config.GetString("username", cs.User));
179 m_log.DebugFormat("[IRC-Channel-{0}] User : <{1}>", cs.idn, cs.User); 179 m_log.DebugFormat("[IRC-Channel-{0}] User : <{1}>", cs.idn, cs.User);
180 cs.CommandsEnabled = Convert.ToBoolean(Substitute(rs, config.GetString("commands_enabled", Convert.ToString(cs.CommandsEnabled)))); 180 cs.CommandsEnabled = Convert.ToBoolean(Substitute(rs, config.GetString("commands_enabled", Convert.ToString(cs.CommandsEnabled))));
181 m_log.DebugFormat("[IRC-Channel-{0}] CommandsEnabled : <{1}>", cs.idn, cs.CommandsEnabled); 181 m_log.DebugFormat("[IRC-Channel-{0}] CommandsEnabled : <{1}>", cs.idn, cs.CommandsEnabled);
182 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("commandchannel", Convert.ToString(cs.CommandChannel)))); 182 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("commandchannel", Convert.ToString(cs.CommandChannel))));
183 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel); 183 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
184 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("command_channel", Convert.ToString(cs.CommandChannel)))); 184 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("command_channel", Convert.ToString(cs.CommandChannel))));
185 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel); 185 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
186 cs.RelayChat = Convert.ToBoolean(Substitute(rs, config.GetString("relay_chat", Convert.ToString(cs.RelayChat)))); 186 cs.RelayChat = Convert.ToBoolean(Substitute(rs, config.GetString("relay_chat", Convert.ToString(cs.RelayChat))));
187 m_log.DebugFormat("[IRC-Channel-{0}] RelayChat : <{1}>", cs.idn, cs.RelayChat); 187 m_log.DebugFormat("[IRC-Channel-{0}] RelayChat : <{1}>", cs.idn, cs.RelayChat);
188 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("relay_private_channels", Convert.ToString(cs.RelayPrivateChannels)))); 188 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("relay_private_channels", Convert.ToString(cs.RelayPrivateChannels))));
189 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels); 189 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
190 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("useworldcomm", Convert.ToString(cs.RelayPrivateChannels)))); 190 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("useworldcomm", Convert.ToString(cs.RelayPrivateChannels))));
191 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels); 191 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
192 cs.RelayChannelOut = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_out", Convert.ToString(cs.RelayChannelOut)))); 192 cs.RelayChannelOut = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_out", Convert.ToString(cs.RelayChannelOut))));
193 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannelOut : <{1}>", cs.idn, cs.RelayChannelOut); 193 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannelOut : <{1}>", cs.idn, cs.RelayChannelOut);
194 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_in", Convert.ToString(cs.RelayChannel)))); 194 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_in", Convert.ToString(cs.RelayChannel))));
195 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel); 195 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
196 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("inchannel", Convert.ToString(cs.RelayChannel)))); 196 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("inchannel", Convert.ToString(cs.RelayChannel))));
197 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel); 197 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
198 cs.PrivateMessageFormat = Substitute(rs, config.GetString("msgformat", cs.PrivateMessageFormat)); 198 cs.PrivateMessageFormat = Substitute(rs, config.GetString("msgformat", cs.PrivateMessageFormat));
199 m_log.DebugFormat("[IRC-Channel-{0}] PrivateMessageFormat : <{1}>", cs.idn, cs.PrivateMessageFormat); 199 m_log.DebugFormat("[IRC-Channel-{0}] PrivateMessageFormat : <{1}>", cs.idn, cs.PrivateMessageFormat);
200 cs.NoticeMessageFormat = Substitute(rs, config.GetString("noticeformat", cs.NoticeMessageFormat)); 200 cs.NoticeMessageFormat = Substitute(rs, config.GetString("noticeformat", cs.NoticeMessageFormat));
201 m_log.DebugFormat("[IRC-Channel-{0}] NoticeMessageFormat : <{1}>", cs.idn, cs.NoticeMessageFormat); 201 m_log.DebugFormat("[IRC-Channel-{0}] NoticeMessageFormat : <{1}>", cs.idn, cs.NoticeMessageFormat);
202 cs.ClientReporting = Convert.ToInt32(Substitute(rs, config.GetString("verbosity", cs.ClientReporting?"1":"0"))) > 0; 202 cs.ClientReporting = Convert.ToInt32(Substitute(rs, config.GetString("verbosity", cs.ClientReporting ? "1" : "0"))) > 0;
203 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting); 203 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
204 cs.ClientReporting = Convert.ToBoolean(Substitute(rs, config.GetString("report_clients", Convert.ToString(cs.ClientReporting)))); 204 cs.ClientReporting = Convert.ToBoolean(Substitute(rs, config.GetString("report_clients", Convert.ToString(cs.ClientReporting))));
205 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting); 205 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
206 cs.DefaultZone = Substitute(rs, config.GetString("fallback_region", cs.DefaultZone)); 206 cs.DefaultZone = Substitute(rs, config.GetString("fallback_region", cs.DefaultZone));
207 m_log.DebugFormat("[IRC-Channel-{0}] DefaultZone : <{1}>", cs.idn, cs.DefaultZone); 207 m_log.DebugFormat("[IRC-Channel-{0}] DefaultZone : <{1}>", cs.idn, cs.DefaultZone);
208 cs.ConnectDelay = Convert.ToInt32(Substitute(rs, config.GetString("connect_delay", Convert.ToString(cs.ConnectDelay)))); 208 cs.ConnectDelay = Convert.ToInt32(Substitute(rs, config.GetString("connect_delay", Convert.ToString(cs.ConnectDelay))));
209 m_log.DebugFormat("[IRC-Channel-{0}] ConnectDelay : <{1}>", cs.idn, cs.ConnectDelay); 209 m_log.DebugFormat("[IRC-Channel-{0}] ConnectDelay : <{1}>", cs.idn, cs.ConnectDelay);
210 cs.PingDelay = Convert.ToInt32(Substitute(rs, config.GetString("ping_delay", Convert.ToString(cs.PingDelay)))); 210 cs.PingDelay = Convert.ToInt32(Substitute(rs, config.GetString("ping_delay", Convert.ToString(cs.PingDelay))));
211 m_log.DebugFormat("[IRC-Channel-{0}] PingDelay : <{1}>", cs.idn, cs.PingDelay); 211 m_log.DebugFormat("[IRC-Channel-{0}] PingDelay : <{1}>", cs.idn, cs.PingDelay);
212 cs.AccessPassword = Substitute(rs, config.GetString("access_password", cs.AccessPassword)); 212 cs.AccessPassword = Substitute(rs, config.GetString("access_password", cs.AccessPassword));
213 m_log.DebugFormat("[IRC-Channel-{0}] AccessPassword : <{1}>", cs.idn, cs.AccessPassword); 213 m_log.DebugFormat("[IRC-Channel-{0}] AccessPassword : <{1}>", cs.idn, cs.AccessPassword);
@@ -217,7 +217,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
217 { 217 {
218 cs.ExcludeList.Add(name.Trim().ToLower()); 218 cs.ExcludeList.Add(name.Trim().ToLower());
219 } 219 }
220 220
221 // Fail if fundamental information is still missing 221 // Fail if fundamental information is still missing
222 222
223 if (cs.Server == null) 223 if (cs.Server == null)
@@ -306,8 +306,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
306 306
307 IRCBridgeModule.m_channels.Add(cs); 307 IRCBridgeModule.m_channels.Add(cs);
308 308
309 m_log.InfoFormat("[IRC-Channel-{0}] New channel initialized for {1}, nick: {2}, commands {3}, private channels {4}", 309 m_log.InfoFormat("[IRC-Channel-{0}] New channel initialized for {1}, nick: {2}, commands {3}, private channels {4}",
310 cs.idn, rs.Region, cs.DefaultZone, 310 cs.idn, rs.Region, cs.DefaultZone,
311 cs.CommandsEnabled ? "enabled" : "not enabled", 311 cs.CommandsEnabled ? "enabled" : "not enabled",
312 cs.RelayPrivateChannels ? "relayed" : "not relayed"); 312 cs.RelayPrivateChannels ? "relayed" : "not relayed");
313 } 313 }
@@ -417,7 +417,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
417 private bool IsAConnectionMatchFor(ChannelState cs) 417 private bool IsAConnectionMatchFor(ChannelState cs)
418 { 418 {
419 return ( 419 return (
420 Server == cs.Server && 420 Server == cs.Server &&
421 IrcChannel == cs.IrcChannel && 421 IrcChannel == cs.IrcChannel &&
422 Port == cs.Port && 422 Port == cs.Port &&
423 BaseNickname == cs.BaseNickname && 423 BaseNickname == cs.BaseNickname &&
@@ -473,27 +473,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
473 { 473 {
474 474
475 string vvar = arg.Match(result).ToString(); 475 string vvar = arg.Match(result).ToString();
476 string var = vvar.Substring(1,vvar.Length-2).Trim(); 476 string var = vvar.Substring(1, vvar.Length - 2).Trim();
477 477
478 switch (var.ToLower()) 478 switch (var.ToLower())
479 { 479 {
480 case "%region" : 480 case "%region":
481 result = result.Replace(vvar, rs.Region); 481 result = result.Replace(vvar, rs.Region);
482 break; 482 break;
483 case "%host" : 483 case "%host":
484 result = result.Replace(vvar, rs.Host); 484 result = result.Replace(vvar, rs.Host);
485 break; 485 break;
486 case "%locx" : 486 case "%locx":
487 result = result.Replace(vvar, rs.LocX); 487 result = result.Replace(vvar, rs.LocX);
488 break; 488 break;
489 case "%locy" : 489 case "%locy":
490 result = result.Replace(vvar, rs.LocY); 490 result = result.Replace(vvar, rs.LocY);
491 break; 491 break;
492 case "%k" : 492 case "%k":
493 result = result.Replace(vvar, rs.IDK); 493 result = result.Replace(vvar, rs.IDK);
494 break; 494 break;
495 default : 495 default:
496 result = result.Replace(vvar, rs.config.GetString(var,var)); 496 result = result.Replace(vvar, rs.config.GetString(var, var));
497 break; 497 break;
498 } 498 }
499 // m_log.DebugFormat("[IRC-Channel] Parse[2]: {0}", result); 499 // m_log.DebugFormat("[IRC-Channel] Parse[2]: {0}", result);
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs
index 2e1d03d..351dbfe 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs
@@ -46,18 +46,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
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 internal static bool m_pluginEnabled = false; 49 internal static bool Enabled = false;
50 internal static IConfig m_config = null; 50 internal static IConfig m_config = null;
51 51
52 internal static List<ChannelState> m_channels = new List<ChannelState>(); 52 internal static List<ChannelState> m_channels = new List<ChannelState>();
53 internal static List<RegionState> m_regions = new List<RegionState>(); 53 internal static List<RegionState> m_regions = new List<RegionState>();
54 54
55 internal static string m_password = String.Empty; 55 internal static string m_password = String.Empty;
56 internal RegionState m_region = null; 56 internal RegionState m_region = null;
57 57
58 #region INonSharedRegionModule Members 58 #region INonSharedRegionModule Members
59 59
60 public Type ReplaceableInterface 60 public Type ReplaceableInterface
61 { 61 {
62 get { return null; } 62 get { return null; }
63 } 63 }
@@ -72,13 +72,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
72 m_config = config.Configs["IRC"]; 72 m_config = config.Configs["IRC"];
73 if (m_config == null) 73 if (m_config == null)
74 { 74 {
75// m_log.InfoFormat("[IRC-Bridge] module not configured"); 75 // m_log.InfoFormat("[IRC-Bridge] module not configured");
76 return; 76 return;
77 } 77 }
78 78
79 if (!m_config.GetBoolean("enabled", false)) 79 if (!m_config.GetBoolean("enabled", false))
80 { 80 {
81// m_log.InfoFormat("[IRC-Bridge] module disabled in configuration"); 81 // m_log.InfoFormat("[IRC-Bridge] module disabled in configuration");
82 return; 82 return;
83 } 83 }
84 84
@@ -87,19 +87,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
87 m_password = config.Configs["RemoteAdmin"].GetString("access_password", m_password); 87 m_password = config.Configs["RemoteAdmin"].GetString("access_password", m_password);
88 } 88 }
89 89
90 m_pluginEnabled = true; 90 Enabled = true;
91 m_log.InfoFormat("[IRC-Bridge]: Module enabled"); 91
92 m_log.InfoFormat("[IRC-Bridge]: Module is enabled");
92 } 93 }
93 94
94 public void AddRegion(Scene scene) 95 public void AddRegion(Scene scene)
95 { 96 {
96 if (m_pluginEnabled) 97 if (Enabled)
97 { 98 {
98 try 99 try
99 { 100 {
100 m_log.InfoFormat("[IRC-Bridge] Connecting region {0}", scene.RegionInfo.RegionName); 101 m_log.InfoFormat("[IRC-Bridge] Connecting region {0}", scene.RegionInfo.RegionName);
102
101 if (!String.IsNullOrEmpty(m_password)) 103 if (!String.IsNullOrEmpty(m_password))
102 MainServer.Instance.AddXmlRPCHandler("irc_admin", XmlRpcAdminMethod, false); 104 MainServer.Instance.AddXmlRPCHandler("irc_admin", XmlRpcAdminMethod, false);
105
103 m_region = new RegionState(scene, m_config); 106 m_region = new RegionState(scene, m_config);
104 lock (m_regions) m_regions.Add(m_region); 107 lock (m_regions) m_regions.Add(m_region);
105 m_region.Open(); 108 m_region.Open();
@@ -123,7 +126,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
123 126
124 public void RemoveRegion(Scene scene) 127 public void RemoveRegion(Scene scene)
125 { 128 {
126 if (!m_pluginEnabled) 129 if (!Enabled)
127 return; 130 return;
128 131
129 if (m_region == null) 132 if (m_region == null)
@@ -150,12 +153,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
150 m_log.Debug("[IRC-Bridge]: XML RPC Admin Entry"); 153 m_log.Debug("[IRC-Bridge]: XML RPC Admin Entry");
151 154
152 XmlRpcResponse response = new XmlRpcResponse(); 155 XmlRpcResponse response = new XmlRpcResponse();
153 Hashtable responseData = new Hashtable(); 156 Hashtable responseData = new Hashtable();
154 157
155 try 158 try
156 { 159 {
157 Hashtable requestData = (Hashtable)request.Params[0]; 160 Hashtable requestData = (Hashtable)request.Params[0];
158 bool found = false; 161 bool found = false;
159 string region = String.Empty; 162 string region = String.Empty;
160 163
161 if (m_password != String.Empty) 164 if (m_password != String.Empty)
@@ -169,18 +172,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
169 if (!requestData.ContainsKey("region")) 172 if (!requestData.ContainsKey("region"))
170 throw new Exception("No region name specified"); 173 throw new Exception("No region name specified");
171 region = (string)requestData["region"]; 174 region = (string)requestData["region"];
172 175
173 foreach (RegionState rs in m_regions) 176 foreach (RegionState rs in m_regions)
174 { 177 {
175 if (rs.Region == region) 178 if (rs.Region == region)
176 { 179 {
177 responseData["server"] = rs.cs.Server; 180 responseData["server"] = rs.cs.Server;
178 responseData["port"] = (int)rs.cs.Port; 181 responseData["port"] = (int)rs.cs.Port;
179 responseData["user"] = rs.cs.User; 182 responseData["user"] = rs.cs.User;
180 responseData["channel"] = rs.cs.IrcChannel; 183 responseData["channel"] = rs.cs.IrcChannel;
181 responseData["enabled"] = rs.cs.irc.Enabled; 184 responseData["enabled"] = rs.cs.irc.Enabled;
182 responseData["connected"] = rs.cs.irc.Connected; 185 responseData["connected"] = rs.cs.irc.Connected;
183 responseData["nickname"] = rs.cs.irc.Nick; 186 responseData["nickname"] = rs.cs.irc.Nick;
184 found = true; 187 found = true;
185 break; 188 break;
186 } 189 }
@@ -195,7 +198,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
195 m_log.ErrorFormat("[IRC-Bridge] XML RPC Admin request failed : {0}", e.Message); 198 m_log.ErrorFormat("[IRC-Bridge] XML RPC Admin request failed : {0}", e.Message);
196 199
197 responseData["success"] = "false"; 200 responseData["success"] = "false";
198 responseData["error"] = e.Message; 201 responseData["error"] = e.Message;
199 } 202 }
200 finally 203 finally
201 { 204 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
index a014798..c5cba8e 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
@@ -53,16 +53,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
53 // Local constants 53 // Local constants
54 54
55 private static readonly Vector3 CenterOfRegion = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20); 55 private static readonly Vector3 CenterOfRegion = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
56 private static readonly char[] CS_SPACE = { ' ' }; 56 private static readonly char[] CS_SPACE = { ' ' };
57 57
58 private const int WD_INTERVAL = 1000; // base watchdog interval 58 private const int WD_INTERVAL = 1000; // base watchdog interval
59 private static int PING_PERIOD = 15; // WD intervals per PING 59 private static int PING_PERIOD = 15; // WD intervals per PING
60 private static int ICCD_PERIOD = 10; // WD intervals between Connects 60 private static int ICCD_PERIOD = 10; // WD intervals between Connects
61 private static int L_TIMEOUT = 25; // Login time out interval 61 private static int L_TIMEOUT = 25; // Login time out interval
62 62
63 private static int _idk_ = 0; // core connector identifier 63 private static int _idk_ = 0; // core connector identifier
64 private static int _pdk_ = 0; // ping interval counter 64 private static int _pdk_ = 0; // ping interval counter
65 private static int _icc_ = ICCD_PERIOD; // IRC connect counter 65 private static int _icc_ = ICCD_PERIOD; // IRC connect counter
66 66
67 // List of configured connectors 67 // List of configured connectors
68 68
@@ -113,7 +113,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
113 113
114 private Object msyncConnect = new Object(); 114 private Object msyncConnect = new Object();
115 115
116 internal bool m_randomizeNick = true; // add random suffix 116 internal bool m_randomizeNick = true; // add random suffix
117 internal string m_baseNick = null; // base name for randomizing 117 internal string m_baseNick = null; // base name for randomizing
118 internal string m_nick = null; // effective nickname 118 internal string m_nick = null; // effective nickname
119 119
@@ -122,7 +122,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
122 get { return m_nick; } 122 get { return m_nick; }
123 set { m_nick = value; } 123 set { m_nick = value; }
124 } 124 }
125 125
126 private bool m_enabled = false; // connector enablement 126 private bool m_enabled = false; // connector enablement
127 public bool Enabled 127 public bool Enabled
128 { 128 {
@@ -130,8 +130,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
130 } 130 }
131 131
132 private bool m_connected = false; // connection status 132 private bool m_connected = false; // connection status
133 private bool m_pending = false; // login disposition 133 private bool m_pending = false; // login disposition
134 private int m_timeout = L_TIMEOUT; // login timeout counter 134 private int m_timeout = L_TIMEOUT; // login timeout counter
135 public bool Connected 135 public bool Connected
136 { 136 {
137 get { return m_connected; } 137 get { return m_connected; }
@@ -143,9 +143,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
143 get { return m_ircChannel; } 143 get { return m_ircChannel; }
144 set { m_ircChannel = value; } 144 set { m_ircChannel = value; }
145 } 145 }
146 146
147 private uint m_port = 6667; // session port 147 private uint m_port = 6667; // session port
148 public uint Port 148 public uint Port
149 { 149 {
150 get { return m_port; } 150 get { return m_port; }
151 set { m_port = value; } 151 set { m_port = value; }
@@ -172,10 +172,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
172 172
173 // Network interface 173 // Network interface
174 174
175 private TcpClient m_tcp; 175 private TcpClient m_tcp;
176 private NetworkStream m_stream = null; 176 private NetworkStream m_stream = null;
177 private StreamReader m_reader; 177 private StreamReader m_reader;
178 private StreamWriter m_writer; 178 private StreamWriter m_writer;
179 179
180 // Channel characteristic info (if available) 180 // Channel characteristic info (if available)
181 181
@@ -193,26 +193,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
193 193
194 // Prepare network interface 194 // Prepare network interface
195 195
196 m_tcp = null; 196 m_tcp = null;
197 m_writer = null; 197 m_writer = null;
198 m_reader = null; 198 m_reader = null;
199 199
200 // Setup IRC session parameters 200 // Setup IRC session parameters
201 201
202 m_server = cs.Server; 202 m_server = cs.Server;
203 m_password = cs.Password; 203 m_password = cs.Password;
204 m_baseNick = cs.BaseNickname; 204 m_baseNick = cs.BaseNickname;
205 m_randomizeNick = cs.RandomizeNickname; 205 m_randomizeNick = cs.RandomizeNickname;
206 m_ircChannel = cs.IrcChannel; 206 m_ircChannel = cs.IrcChannel;
207 m_port = cs.Port; 207 m_port = cs.Port;
208 m_user = cs.User; 208 m_user = cs.User;
209 209
210 if (m_watchdog == null) 210 if (m_watchdog == null)
211 { 211 {
212 // Non-differentiating 212 // Non-differentiating
213 213
214 ICCD_PERIOD = cs.ConnectDelay; 214 ICCD_PERIOD = cs.ConnectDelay;
215 PING_PERIOD = cs.PingDelay; 215 PING_PERIOD = cs.PingDelay;
216 216
217 // Smaller values are not reasonable 217 // Smaller values are not reasonable
218 218
@@ -235,7 +235,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
235 235
236 if (m_randomizeNick) 236 if (m_randomizeNick)
237 m_nick = m_baseNick + Util.RandomClass.Next(1, 99); 237 m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
238 else 238 else
239 m_nick = m_baseNick; 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);
@@ -295,18 +295,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
295 m_nick, m_ircChannel, m_server)); 295 m_nick, m_ircChannel, m_server));
296 m_writer.Flush(); 296 m_writer.Flush();
297 } 297 }
298 catch (Exception) {} 298 catch (Exception) { }
299 299
300 300
301 m_connected = false; 301 m_connected = false;
302 302
303 try { m_writer.Close(); } catch (Exception) {} 303 try { m_writer.Close(); }
304 try { m_reader.Close(); } catch (Exception) {} 304 catch (Exception) { }
305 try { m_stream.Close(); } catch (Exception) {} 305 try { m_reader.Close(); }
306 try { m_tcp.Close(); } catch (Exception) {} 306 catch (Exception) { }
307 try { m_stream.Close(); }
308 catch (Exception) { }
309 try { m_tcp.Close(); }
310 catch (Exception) { }
307 311
308 } 312 }
309 313
310 lock (m_connectors) 314 lock (m_connectors)
311 m_connectors.Remove(this); 315 m_connectors.Remove(this);
312 316
@@ -347,15 +351,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
347 if (m_connected) return; 351 if (m_connected) return;
348 352
349 m_connected = true; 353 m_connected = true;
350 m_pending = true; 354 m_pending = true;
351 m_timeout = L_TIMEOUT; 355 m_timeout = L_TIMEOUT;
352 356
353 m_tcp = new TcpClient(m_server, (int)m_port); 357 m_tcp = new TcpClient(m_server, (int)m_port);
354 m_stream = m_tcp.GetStream(); 358 m_stream = m_tcp.GetStream();
355 m_reader = new StreamReader(m_stream); 359 m_reader = new StreamReader(m_stream);
356 m_writer = new StreamWriter(m_stream); 360 m_writer = new StreamWriter(m_stream);
357 361
358 m_log.InfoFormat("[IRC-Connector-{0}]: Connected to {1}:{2}", idn, m_server, m_port); 362 m_log.InfoFormat("[IRC-Connector-{0}]: Connected to {1}:{2}", idn, m_server, m_port);
359 363
360 m_listener = new Thread(new ThreadStart(ListenerRun)); 364 m_listener = new Thread(new ThreadStart(ListenerRun));
361 m_listener.Name = "IRCConnectorListenerThread"; 365 m_listener.Name = "IRCConnectorListenerThread";
@@ -418,12 +422,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
418 // the socket and it will disappear of its own accord, once this 422 // the socket and it will disappear of its own accord, once this
419 // processing is completed. 423 // processing is completed.
420 424
421 try { m_writer.Close(); } catch (Exception) {} 425 try { m_writer.Close(); }
422 try { m_reader.Close(); } catch (Exception) {} 426 catch (Exception) { }
423 try { m_tcp.Close(); } catch (Exception) {} 427 try { m_reader.Close(); }
428 catch (Exception) { }
429 try { m_tcp.Close(); }
430 catch (Exception) { }
424 431
425 m_connected = false; 432 m_connected = false;
426 m_pending = false; 433 m_pending = false;
427 m_resetk++; 434 m_resetk++;
428 435
429 } 436 }
@@ -495,7 +502,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
495 { 502 {
496 503
497 string inputLine; 504 string inputLine;
498 int resetk = m_resetk; 505 int resetk = m_resetk;
499 506
500 try 507 try
501 { 508 {
@@ -555,7 +562,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
555 Reconnect(); 562 Reconnect();
556 } 563 }
557 564
558 private Regex RE = new Regex(@":(?<nick>[\w-]*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)", 565 private Regex RE = new Regex(@":(?<nick>[\w-]*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)",
559 RegexOptions.Multiline); 566 RegexOptions.Multiline);
560 567
561 private Dictionary<string, string> ExtractMsg(string input) 568 private Dictionary<string, string> ExtractMsg(string input)
@@ -617,8 +624,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
617 string[] commArgs; 624 string[] commArgs;
618 string c_server = m_server; 625 string c_server = m_server;
619 626
620 string pfx = String.Empty; 627 string pfx = String.Empty;
621 string cmd = String.Empty; 628 string cmd = String.Empty;
622 string parms = String.Empty; 629 string parms = String.Empty;
623 630
624 // ":" indicates that a prefix is present 631 // ":" indicates that a prefix is present
@@ -627,15 +634,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
627 // ":" indicates that the remainder of the 634 // ":" indicates that the remainder of the
628 // line is a single parameter value. 635 // line is a single parameter value.
629 636
630 commArgs = command.Split(CS_SPACE,2); 637 commArgs = command.Split(CS_SPACE, 2);
631 638
632 if (commArgs[0].StartsWith(":")) 639 if (commArgs[0].StartsWith(":"))
633 { 640 {
634 pfx = commArgs[0].Substring(1); 641 pfx = commArgs[0].Substring(1);
635 commArgs = commArgs[1].Split(CS_SPACE,2); 642 commArgs = commArgs[1].Split(CS_SPACE, 2);
636 } 643 }
637 644
638 cmd = commArgs[0]; 645 cmd = commArgs[0];
639 parms = commArgs[1]; 646 parms = commArgs[1];
640 647
641 // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}>", idn, pfx, cmd); 648 // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}>", idn, pfx, cmd);
@@ -646,44 +653,44 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
646 // Messages 001-004 are always sent 653 // Messages 001-004 are always sent
647 // following signon. 654 // following signon.
648 655
649 case "001" : // Welcome ... 656 case "001": // Welcome ...
650 case "002" : // Server information 657 case "002": // Server information
651 case "003" : // Welcome ... 658 case "003": // Welcome ...
652 break; 659 break;
653 case "004" : // Server information 660 case "004": // Server information
654 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); 661 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
655 commArgs = parms.Split(CS_SPACE); 662 commArgs = parms.Split(CS_SPACE);
656 c_server = commArgs[1]; 663 c_server = commArgs[1];
657 m_server = c_server; 664 m_server = c_server;
658 version = commArgs[2]; 665 version = commArgs[2];
659 usermod = commArgs[3]; 666 usermod = commArgs[3];
660 chanmod = commArgs[4]; 667 chanmod = commArgs[4];
661 break; 668 break;
662 case "005" : // Server information 669 case "005": // Server information
663 break; 670 break;
664 case "042" : 671 case "042":
665 case "250" : 672 case "250":
666 case "251" : 673 case "251":
667 case "252" : 674 case "252":
668 case "254" : 675 case "254":
669 case "255" : 676 case "255":
670 case "265" : 677 case "265":
671 case "266" : 678 case "266":
672 case "332" : // Subject 679 case "332": // Subject
673 case "333" : // Subject owner (?) 680 case "333": // Subject owner (?)
674 case "353" : // Name list 681 case "353": // Name list
675 case "366" : // End-of-Name list marker 682 case "366": // End-of-Name list marker
676 case "372" : // MOTD body 683 case "372": // MOTD body
677 case "375" : // MOTD start 684 case "375": // MOTD start
678 // m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); 685 // m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
679 break; 686 break;
680 case "376" : // MOTD end 687 case "376": // MOTD end
681 // m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); 688 // m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
682 motd = true; 689 motd = true;
683 break; 690 break;
684 case "451" : // Not registered 691 case "451": // Not registered
685 break; 692 break;
686 case "433" : // Nickname in use 693 case "433": // Nickname in use
687 // Gen a new name 694 // Gen a new name
688 m_nick = m_baseNick + Util.RandomClass.Next(1, 99); 695 m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
689 m_log.ErrorFormat("[IRC-Connector-{0}]: [{1}] IRC SERVER reports NicknameInUse, trying {2}", idn, cmd, m_nick); 696 m_log.ErrorFormat("[IRC-Connector-{0}]: [{1}] IRC SERVER reports NicknameInUse, trying {2}", idn, cmd, m_nick);
@@ -695,29 +702,29 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
695 m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel)); 702 m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel));
696 m_writer.Flush(); 703 m_writer.Flush();
697 break; 704 break;
698 case "479" : // Bad channel name, etc. This will never work, so disable the connection 705 case "479": // Bad channel name, etc. This will never work, so disable the connection
699 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); 706 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE, 2)[1]);
700 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] Connector disabled", idn, cmd); 707 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] Connector disabled", idn, cmd);
701 m_enabled = false; 708 m_enabled = false;
702 m_connected = false; 709 m_connected = false;
703 m_pending = false; 710 m_pending = false;
704 break; 711 break;
705 case "NOTICE" : 712 case "NOTICE":
706 // m_log.WarnFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); 713 // m_log.WarnFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
707 break; 714 break;
708 case "ERROR" : 715 case "ERROR":
709 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); 716 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE, 2)[1]);
710 if (parms.Contains("reconnect too fast")) 717 if (parms.Contains("reconnect too fast"))
711 ICCD_PERIOD++; 718 ICCD_PERIOD++;
712 m_pending = false; 719 m_pending = false;
713 Reconnect(); 720 Reconnect();
714 break; 721 break;
715 case "PING" : 722 case "PING":
716 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); 723 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
717 m_writer.WriteLine(String.Format("PONG {0}", parms)); 724 m_writer.WriteLine(String.Format("PONG {0}", parms));
718 m_writer.Flush(); 725 m_writer.Flush();
719 break; 726 break;
720 case "PONG" : 727 case "PONG":
721 break; 728 break;
722 case "JOIN": 729 case "JOIN":
723 if (m_pending) 730 if (m_pending)
@@ -748,19 +755,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
748 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); 755 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
749 eventIrcQuit(pfx, cmd, parms); 756 eventIrcQuit(pfx, cmd, parms);
750 break; 757 break;
751 default : 758 default:
752 m_log.DebugFormat("[IRC-Connector-{0}] Command '{1}' ignored, parms = {2}", idn, cmd, parms); 759 m_log.DebugFormat("[IRC-Connector-{0}] Command '{1}' ignored, parms = {2}", idn, cmd, parms);
753 break; 760 break;
754 } 761 }
755 762
756 // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}> complete", idn, pfx, cmd); 763 // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}> complete", idn, pfx, cmd);
757 764
758 } 765 }
759 766
760 public void eventIrcJoin(string prefix, string command, string parms) 767 public void eventIrcJoin(string prefix, string command, string parms)
761 { 768 {
762 string[] args = parms.Split(CS_SPACE,2); 769 string[] args = parms.Split(CS_SPACE, 2);
763 string IrcUser = prefix.Split('!')[0]; 770 string IrcUser = prefix.Split('!')[0];
764 string IrcChannel = args[0]; 771 string IrcChannel = args[0];
765 772
766 if (IrcChannel.StartsWith(":")) 773 if (IrcChannel.StartsWith(":"))
@@ -772,8 +779,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
772 779
773 public void eventIrcPart(string prefix, string command, string parms) 780 public void eventIrcPart(string prefix, string command, string parms)
774 { 781 {
775 string[] args = parms.Split(CS_SPACE,2); 782 string[] args = parms.Split(CS_SPACE, 2);
776 string IrcUser = prefix.Split('!')[0]; 783 string IrcUser = prefix.Split('!')[0];
777 string IrcChannel = args[0]; 784 string IrcChannel = args[0];
778 785
779 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCPart {1}:{2}", idn, m_server, m_ircChannel); 786 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCPart {1}:{2}", idn, m_server, m_ircChannel);
@@ -782,7 +789,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
782 789
783 public void eventIrcMode(string prefix, string command, string parms) 790 public void eventIrcMode(string prefix, string command, string parms)
784 { 791 {
785 string[] args = parms.Split(CS_SPACE,2); 792 string[] args = parms.Split(CS_SPACE, 2);
786 string UserMode = args[1]; 793 string UserMode = args[1];
787 794
788 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCMode {1}:{2}", idn, m_server, m_ircChannel); 795 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCMode {1}:{2}", idn, m_server, m_ircChannel);
@@ -794,7 +801,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
794 801
795 public void eventIrcNickChange(string prefix, string command, string parms) 802 public void eventIrcNickChange(string prefix, string command, string parms)
796 { 803 {
797 string[] args = parms.Split(CS_SPACE,2); 804 string[] args = parms.Split(CS_SPACE, 2);
798 string UserOldNick = prefix.Split('!')[0]; 805 string UserOldNick = prefix.Split('!')[0];
799 string UserNewNick = args[0].Remove(0, 1); 806 string UserNewNick = args[0].Remove(0, 1);
800 807
@@ -804,11 +811,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
804 811
805 public void eventIrcKick(string prefix, string command, string parms) 812 public void eventIrcKick(string prefix, string command, string parms)
806 { 813 {
807 string[] args = parms.Split(CS_SPACE,3); 814 string[] args = parms.Split(CS_SPACE, 3);
808 string UserKicker = prefix.Split('!')[0]; 815 string UserKicker = prefix.Split('!')[0];
809 string IrcChannel = args[0]; 816 string IrcChannel = args[0];
810 string UserKicked = args[1]; 817 string UserKicked = args[1];
811 string KickMessage = args[2]; 818 string KickMessage = args[2];
812 819
813 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCKick {1}:{2}", idn, m_server, m_ircChannel); 820 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCKick {1}:{2}", idn, m_server, m_ircChannel);
814 BroadcastSim(UserKicker, "/me kicks kicks {0} off {1} saying \"{2}\"", UserKicked, IrcChannel, KickMessage); 821 BroadcastSim(UserKicker, "/me kicks kicks {0} off {1} saying \"{2}\"", UserKicked, IrcChannel, KickMessage);
@@ -822,7 +829,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
822 829
823 public void eventIrcQuit(string prefix, string command, string parms) 830 public void eventIrcQuit(string prefix, string command, string parms)
824 { 831 {
825 string IrcUser = prefix.Split('!')[0]; 832 string IrcUser = prefix.Split('!')[0];
826 string QuitMessage = parms; 833 string QuitMessage = parms;
827 834
828 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCQuit {1}:{2}", idn, m_server, m_ircChannel); 835 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCQuit {1}:{2}", idn, m_server, m_ircChannel);
@@ -842,65 +849,65 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
842 849
843 // m_log.InfoFormat("[IRC-Watchdog] Status scan, pdk = {0}, icc = {1}", _pdk_, _icc_); 850 // m_log.InfoFormat("[IRC-Watchdog] Status scan, pdk = {0}, icc = {1}", _pdk_, _icc_);
844 851
845 _pdk_ = (_pdk_+1)%PING_PERIOD; // cycle the ping trigger 852 _pdk_ = (_pdk_ + 1) % PING_PERIOD; // cycle the ping trigger
846 _icc_++; // increment the inter-consecutive-connect-delay counter 853 _icc_++; // increment the inter-consecutive-connect-delay counter
847 854
848 lock (m_connectors) 855 lock (m_connectors)
849 foreach (IRCConnector connector in m_connectors) 856 foreach (IRCConnector connector in m_connectors)
850 { 857 {
851 858
852 // m_log.InfoFormat("[IRC-Watchdog] Scanning {0}", connector); 859 // m_log.InfoFormat("[IRC-Watchdog] Scanning {0}", connector);
853 860
854 if (connector.Enabled) 861 if (connector.Enabled)
855 {
856 if (!connector.Connected)
857 { 862 {
858 try 863 if (!connector.Connected)
859 { 864 {
860 // m_log.DebugFormat("[IRC-Watchdog] Connecting {1}:{2}", connector.idn, connector.m_server, connector.m_ircChannel); 865 try
861 connector.Connect(); 866 {
867 // m_log.DebugFormat("[IRC-Watchdog] Connecting {1}:{2}", connector.idn, connector.m_server, connector.m_ircChannel);
868 connector.Connect();
869 }
870 catch (Exception e)
871 {
872 m_log.ErrorFormat("[IRC-Watchdog] Exception on connector {0}: {1} ", connector.idn, e.Message);
873 }
862 } 874 }
863 catch (Exception e) 875 else
864 { 876 {
865 m_log.ErrorFormat("[IRC-Watchdog] Exception on connector {0}: {1} ", connector.idn, e.Message);
866 }
867 }
868 else
869 {
870 877
871 if (connector.m_pending) 878 if (connector.m_pending)
872 {
873 if (connector.m_timeout == 0)
874 { 879 {
875 m_log.ErrorFormat("[IRC-Watchdog] Login timed-out for connector {0}, reconnecting", connector.idn); 880 if (connector.m_timeout == 0)
876 connector.Reconnect(); 881 {
882 m_log.ErrorFormat("[IRC-Watchdog] Login timed-out for connector {0}, reconnecting", connector.idn);
883 connector.Reconnect();
884 }
885 else
886 connector.m_timeout--;
877 } 887 }
878 else
879 connector.m_timeout--;
880 }
881 888
882 // Being marked connected is not enough to ping. Socket establishment can sometimes take a long 889 // Being marked connected is not enough to ping. Socket establishment can sometimes take a long
883 // time, in which case the watch dog might try to ping the server before the socket has been 890 // time, in which case the watch dog might try to ping the server before the socket has been
884 // set up, with nasty side-effects. 891 // set up, with nasty side-effects.
885 892
886 else if (_pdk_ == 0) 893 else if (_pdk_ == 0)
887 {
888 try
889 {
890 connector.m_writer.WriteLine(String.Format("PING :{0}", connector.m_server));
891 connector.m_writer.Flush();
892 }
893 catch (Exception e)
894 { 894 {
895 m_log.ErrorFormat("[IRC-PingRun] Exception on connector {0}: {1} ", connector.idn, e.Message); 895 try
896 m_log.Debug(e); 896 {
897 connector.Reconnect(); 897 connector.m_writer.WriteLine(String.Format("PING :{0}", connector.m_server));
898 connector.m_writer.Flush();
899 }
900 catch (Exception e)
901 {
902 m_log.ErrorFormat("[IRC-PingRun] Exception on connector {0}: {1} ", connector.idn, e.Message);
903 m_log.Debug(e);
904 connector.Reconnect();
905 }
898 } 906 }
899 }
900 907
908 }
901 } 909 }
902 } 910 }
903 }
904 911
905 // m_log.InfoFormat("[IRC-Watchdog] Status scan completed"); 912 // m_log.InfoFormat("[IRC-Watchdog] Status scan completed");
906 913
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
index 53b103e..d4fe5e0 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
@@ -41,49 +41,71 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
41 41
42 internal class RegionState 42 internal class RegionState
43 { 43 {
44
45 private static readonly ILog m_log = 44 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 46
48 private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20); 47 private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
49 private const int DEBUG_CHANNEL = 2147483647; 48 private const int DEBUG_CHANNEL = 2147483647;
50 49
51 private static int _idk_ = 0; 50 private static int _idk_ = 0;
52 51
53 // Runtime variables; these values are assigned when the 52 // Runtime variables; these values are assigned when the
54 // IrcState is created and remain constant thereafter. 53 // IrcState is created and remain constant thereafter.
55 54
56 internal string Region = String.Empty; 55 internal string Region = String.Empty;
57 internal string Host = String.Empty; 56 internal string Host = String.Empty;
58 internal string LocX = String.Empty; 57 internal string LocX = String.Empty;
59 internal string LocY = String.Empty; 58 internal string LocY = String.Empty;
60 internal string IDK = String.Empty; 59 internal string IDK = String.Empty;
61 60
62 // System values - used only be the IRC classes themselves 61 // System values - used only be the IRC classes themselves
63 62
64 internal ChannelState cs = null; // associated IRC configuration 63 internal ChannelState cs = null; // associated IRC configuration
65 internal Scene scene = null; // associated scene 64 internal Scene scene = null; // associated scene
66 internal IConfig config = null; // configuration file reference 65 internal IConfig config = null; // configuration file reference
67 internal bool enabled = true; 66 internal bool enabled = true;
68 67
68 //AgentAlert
69 internal bool showAlert = false;
70 internal string alertMessage = String.Empty;
71 internal IDialogModule dialogModule = null;
72
69 // This list is used to keep track of who is here, and by 73 // This list is used to keep track of who is here, and by
70 // implication, who is not. 74 // implication, who is not.
71 75
72 internal List<IClientAPI> clients = new List<IClientAPI>(); 76 internal List<IClientAPI> clients = new List<IClientAPI>();
73 77
74 // Setup runtime variable values 78 // Setup runtime variable values
75 79
76 public RegionState(Scene p_scene, IConfig p_config) 80 public RegionState(Scene p_scene, IConfig p_config)
77 { 81 {
78 82 scene = p_scene;
79 scene = p_scene;
80 config = p_config; 83 config = p_config;
81 84
82 Region = scene.RegionInfo.RegionName; 85 Region = scene.RegionInfo.RegionName;
83 Host = scene.RegionInfo.ExternalHostName; 86 Host = scene.RegionInfo.ExternalHostName;
84 LocX = Convert.ToString(scene.RegionInfo.RegionLocX); 87 LocX = Convert.ToString(scene.RegionInfo.RegionLocX);
85 LocY = Convert.ToString(scene.RegionInfo.RegionLocY); 88 LocY = Convert.ToString(scene.RegionInfo.RegionLocY);
86 IDK = Convert.ToString(_idk_++); 89 IDK = Convert.ToString(_idk_++);
90
91 showAlert = config.GetBoolean("alert_show", false);
92 string alertServerInfo = String.Empty;
93
94 if (showAlert)
95 {
96 bool showAlertServerInfo = config.GetBoolean("alert_show_serverinfo", true);
97
98 if (showAlertServerInfo)
99 alertServerInfo = String.Format("\nServer: {0}\nPort: {1}\nChannel: {2}\n\n",
100 config.GetString("server", ""), config.GetString("port", ""), config.GetString("channel", ""));
101
102 string alertPreMessage = config.GetString("alert_msg_pre", "This region is linked to Irc.");
103 string alertPostMessage = config.GetString("alert_msg_post", "Everything you say in public chat can be listened.");
104
105 alertMessage = String.Format("{0}\n{1}{2}", alertPreMessage, alertServerInfo, alertPostMessage);
106
107 dialogModule = scene.RequestModuleInterface<IDialogModule>();
108 }
87 109
88 // OpenChannel conditionally establishes a connection to the 110 // OpenChannel conditionally establishes a connection to the
89 // IRC server. The request will either succeed, or it will 111 // IRC server. The request will either succeed, or it will
@@ -93,9 +115,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
93 115
94 // Connect channel to world events 116 // Connect channel to world events
95 117
96 scene.EventManager.OnChatFromWorld += OnSimChat; 118 scene.EventManager.OnChatFromWorld += OnSimChat;
97 scene.EventManager.OnChatFromClient += OnSimChat; 119 scene.EventManager.OnChatFromClient += OnSimChat;
98 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; 120 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
99 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; 121 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
100 122
101 m_log.InfoFormat("[IRC-Region {0}] Initialization complete", Region); 123 m_log.InfoFormat("[IRC-Region {0}] Initialization complete", Region);
@@ -106,8 +128,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
106 128
107 ~RegionState() 129 ~RegionState()
108 { 130 {
109 if (cs != null) 131 if (cs != null)
110 cs.RemoveRegion(this); 132 cs.RemoveRegion(this);
111 } 133 }
112 134
113 // Called by PostInitialize after all regions have been created 135 // Called by PostInitialize after all regions have been created
@@ -138,7 +160,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
138 { 160 {
139 if (clients.Contains(client)) 161 if (clients.Contains(client))
140 { 162 {
141 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) 163 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting))
142 { 164 {
143 m_log.InfoFormat("[IRC-Region {0}]: {1} has left", Region, client.Name); 165 m_log.InfoFormat("[IRC-Region {0}]: {1} has left", Region, client.Name);
144 //Check if this person is excluded from IRC 166 //Check if this person is excluded from IRC
@@ -147,7 +169,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
147 cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", client.Name)); 169 cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", client.Name));
148 } 170 }
149 } 171 }
150 client.OnLogout -= OnClientLoggedOut; 172 client.OnLogout -= OnClientLoggedOut;
151 client.OnConnectionClosed -= OnClientLoggedOut; 173 client.OnConnectionClosed -= OnClientLoggedOut;
152 clients.Remove(client); 174 clients.Remove(client);
153 } 175 }
@@ -171,13 +193,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
171 { 193 {
172 if (clients.Contains(client)) 194 if (clients.Contains(client))
173 { 195 {
174 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) 196 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting))
175 { 197 {
176 string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname); 198 string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname);
177 m_log.DebugFormat("[IRC-Region {0}] {1} has left", Region, clientName); 199 m_log.DebugFormat("[IRC-Region {0}] {1} has left", Region, clientName);
178 cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", clientName)); 200 cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", clientName));
179 } 201 }
180 client.OnLogout -= OnClientLoggedOut; 202 client.OnLogout -= OnClientLoggedOut;
181 client.OnConnectionClosed -= OnClientLoggedOut; 203 client.OnConnectionClosed -= OnClientLoggedOut;
182 clients.Remove(client); 204 clients.Remove(client);
183 } 205 }
@@ -195,14 +217,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
195 217
196 private void OnMakeRootAgent(ScenePresence presence) 218 private void OnMakeRootAgent(ScenePresence presence)
197 { 219 {
198
199 IClientAPI client = presence.ControllingClient; 220 IClientAPI client = presence.ControllingClient;
200 221
201 try 222 try
202 { 223 {
203 if (!clients.Contains(client)) 224 if (!clients.Contains(client))
204 { 225 {
205 client.OnLogout += OnClientLoggedOut; 226 client.OnLogout += OnClientLoggedOut;
206 client.OnConnectionClosed += OnClientLoggedOut; 227 client.OnConnectionClosed += OnClientLoggedOut;
207 clients.Add(client); 228 clients.Add(client);
208 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) 229 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting))
@@ -216,17 +237,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
216 } 237 }
217 } 238 }
218 } 239 }
240
241 if (dialogModule != null && showAlert)
242 dialogModule.SendAlertToUser(client, alertMessage, true);
219 } 243 }
220 catch (Exception ex) 244 catch (Exception ex)
221 { 245 {
222 m_log.ErrorFormat("[IRC-Region {0}]: MakeRootAgent exception: {1}", Region, ex.Message); 246 m_log.ErrorFormat("[IRC-Region {0}]: MakeRootAgent exception: {1}", Region, ex.Message);
223 m_log.Debug(ex); 247 m_log.Debug(ex);
224 } 248 }
225
226 } 249 }
227 250
228 // This handler detects chat events int he virtual world. 251 // This handler detects chat events int he virtual world.
229
230 public void OnSimChat(Object sender, OSChatMessage msg) 252 public void OnSimChat(Object sender, OSChatMessage msg)
231 { 253 {
232 254
@@ -317,14 +339,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
317 // that evident. 339 // that evident.
318 340
319 default: 341 default:
320 m_log.DebugFormat("[IRC-Region {0}] Forwarding unrecognized command to IRC : {1}", 342 m_log.DebugFormat("[IRC-Region {0}] Forwarding unrecognized command to IRC : {1}",
321 Region, msg.Message); 343 Region, msg.Message);
322 cs.irc.Send(msg.Message); 344 cs.irc.Send(msg.Message);
323 break; 345 break;
324 } 346 }
325 } 347 }
326 catch (Exception ex) 348 catch (Exception ex)
327 { 349 {
328 m_log.WarnFormat("[IRC-Region {0}] error processing in-world command channel input: {1}", 350 m_log.WarnFormat("[IRC-Region {0}] error processing in-world command channel input: {1}",
329 Region, ex.Message); 351 Region, ex.Message);
330 m_log.Debug(ex); 352 m_log.Debug(ex);
@@ -366,7 +388,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
366 388
367 m_log.DebugFormat("[IRC-Region {0}] heard on channel {1} : {2}", Region, msg.Channel, msg.Message); 389 m_log.DebugFormat("[IRC-Region {0}] heard on channel {1} : {2}", Region, msg.Channel, msg.Message);
368 390
369 if (null != avatar && cs.RelayChat && (msg.Channel == 0 || msg.Channel == DEBUG_CHANNEL)) 391 if (null != avatar && cs.RelayChat && (msg.Channel == 0 || msg.Channel == DEBUG_CHANNEL))
370 { 392 {
371 string txt = msg.Message; 393 string txt = msg.Message;
372 if (txt.StartsWith("/me ")) 394 if (txt.StartsWith("/me "))
@@ -376,13 +398,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
376 return; 398 return;
377 } 399 }
378 400
379 if (null == avatar && cs.RelayPrivateChannels && null != cs.AccessPassword && 401 if (null == avatar && cs.RelayPrivateChannels && null != cs.AccessPassword &&
380 msg.Channel == cs.RelayChannelOut) 402 msg.Channel == cs.RelayChannelOut)
381 { 403 {
382 Match m = cs.AccessPasswordRegex.Match(msg.Message); 404 Match m = cs.AccessPasswordRegex.Match(msg.Message);
383 if (null != m) 405 if (null != m)
384 { 406 {
385 m_log.DebugFormat("[IRC] relaying message from {0}: {1}", m.Groups["avatar"].ToString(), 407 m_log.DebugFormat("[IRC] relaying message from {0}: {1}", m.Groups["avatar"].ToString(),
386 m.Groups["message"].ToString()); 408 m.Groups["message"].ToString());
387 cs.irc.PrivMsg(cs.PrivateMessageFormat, m.Groups["avatar"].ToString(), 409 cs.irc.PrivMsg(cs.PrivateMessageFormat, m.Groups["avatar"].ToString(),
388 scene.RegionInfo.RegionName, m.Groups["message"].ToString()); 410 scene.RegionInfo.RegionName, m.Groups["message"].ToString());
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index ae0ad02..d764936 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -126,7 +126,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
126 { 126 {
127 scene.RegisterModuleInterface<IGroupsModule>(this); 127 scene.RegisterModuleInterface<IGroupsModule>(this);
128 scene.AddCommand( 128 scene.AddCommand(
129 "debug", 129 "Debug",
130 this, 130 this,
131 "debug groups verbose", 131 "debug groups verbose",
132 "debug groups verbose <true|false>", 132 "debug groups verbose <true|false>",
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs
index 6d26075..6b5b40a 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs
@@ -36,7 +36,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
36 { 36 {
37 UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); 37 UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID);
38 void UpdateGroup(UUID RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); 38 void UpdateGroup(UUID RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish);
39
40 /// <summary>
41 /// Get the group record.
42 /// </summary>
43 /// <returns></returns>
44 /// <param name='RequestingAgentID'>The UUID of the user making the request.</param>
45 /// <param name='GroupID'>
46 /// The ID of the record to retrieve.
47 /// GroupName may be specified instead, in which case this parameter will be UUID.Zero
48 /// </param>
49 /// <param name='GroupName'>
50 /// The name of the group to retrieve.
51 /// GroupID may be specified instead, in which case this parmeter will be null.
52 /// </param>
39 GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName); 53 GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName);
54
40 List<DirGroupsReplyData> FindGroups(UUID RequestingAgentID, string search); 55 List<DirGroupsReplyData> FindGroups(UUID RequestingAgentID, string search);
41 List<GroupMembersData> GetGroupMembers(UUID RequestingAgentID, UUID GroupID); 56 List<GroupMembersData> GetGroupMembers(UUID RequestingAgentID, UUID GroupID);
42 57
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
index ac638f1..c1bdacb 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
42 /// Basic groups module tests 42 /// Basic groups module tests
43 /// </summary> 43 /// </summary>
44 [TestFixture] 44 [TestFixture]
45 public class GroupsModuleTests 45 public class GroupsModuleTests : OpenSimTestCase
46 { 46 {
47 [Test] 47 [Test]
48 public void TestBasic() 48 public void TestBasic()
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
index d0c3ea5..1101851 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
@@ -54,13 +54,62 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
54 54
55 private bool m_debugEnabled = false; 55 private bool m_debugEnabled = false;
56 56
57 public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | 57 public const GroupPowers DefaultEveryonePowers
58 GroupPowers.Accountable | 58 = GroupPowers.AllowSetHome
59 GroupPowers.JoinChat | 59 | GroupPowers.Accountable
60 GroupPowers.AllowVoiceChat | 60 | GroupPowers.JoinChat
61 GroupPowers.ReceiveNotices | 61 | GroupPowers.AllowVoiceChat
62 GroupPowers.StartProposal | 62 | GroupPowers.ReceiveNotices
63 GroupPowers.VoteOnProposal; 63 | GroupPowers.StartProposal
64 | GroupPowers.VoteOnProposal;
65
66 // Would this be cleaner as (GroupPowers)ulong.MaxValue?
67 public const GroupPowers DefaultOwnerPowers
68 = GroupPowers.Accountable
69 | GroupPowers.AllowEditLand
70 | GroupPowers.AllowFly
71 | GroupPowers.AllowLandmark
72 | GroupPowers.AllowRez
73 | GroupPowers.AllowSetHome
74 | GroupPowers.AllowVoiceChat
75 | GroupPowers.AssignMember
76 | GroupPowers.AssignMemberLimited
77 | GroupPowers.ChangeActions
78 | GroupPowers.ChangeIdentity
79 | GroupPowers.ChangeMedia
80 | GroupPowers.ChangeOptions
81 | GroupPowers.CreateRole
82 | GroupPowers.DeedObject
83 | GroupPowers.DeleteRole
84 | GroupPowers.Eject
85 | GroupPowers.FindPlaces
86 | GroupPowers.Invite
87 | GroupPowers.JoinChat
88 | GroupPowers.LandChangeIdentity
89 | GroupPowers.LandDeed
90 | GroupPowers.LandDivideJoin
91 | GroupPowers.LandEdit
92 | GroupPowers.LandEjectAndFreeze
93 | GroupPowers.LandGardening
94 | GroupPowers.LandManageAllowed
95 | GroupPowers.LandManageBanned
96 | GroupPowers.LandManagePasses
97 | GroupPowers.LandOptions
98 | GroupPowers.LandRelease
99 | GroupPowers.LandSetSale
100 | GroupPowers.ModerateChat
101 | GroupPowers.ObjectManipulate
102 | GroupPowers.ObjectSetForSale
103 | GroupPowers.ReceiveNotices
104 | GroupPowers.RemoveMember
105 | GroupPowers.ReturnGroupOwned
106 | GroupPowers.ReturnGroupSet
107 | GroupPowers.ReturnNonGroup
108 | GroupPowers.RoleProperties
109 | GroupPowers.SendNotices
110 | GroupPowers.SetLandingPoint
111 | GroupPowers.StartProposal
112 | GroupPowers.VoteOnProposal;
64 113
65 private bool m_connectorEnabled = false; 114 private bool m_connectorEnabled = false;
66 115
@@ -219,59 +268,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
219 param["AllowPublish"] = allowPublish == true ? 1 : 0; 268 param["AllowPublish"] = allowPublish == true ? 1 : 0;
220 param["MaturePublish"] = maturePublish == true ? 1 : 0; 269 param["MaturePublish"] = maturePublish == true ? 1 : 0;
221 param["FounderID"] = founderID.ToString(); 270 param["FounderID"] = founderID.ToString();
222 param["EveryonePowers"] = ((ulong)m_DefaultEveryonePowers).ToString(); 271 param["EveryonePowers"] = ((ulong)DefaultEveryonePowers).ToString();
223 param["OwnerRoleID"] = OwnerRoleID.ToString(); 272 param["OwnerRoleID"] = OwnerRoleID.ToString();
224 273 param["OwnersPowers"] = ((ulong)DefaultOwnerPowers).ToString();
225 // Would this be cleaner as (GroupPowers)ulong.MaxValue;
226 GroupPowers OwnerPowers = GroupPowers.Accountable
227 | GroupPowers.AllowEditLand
228 | GroupPowers.AllowFly
229 | GroupPowers.AllowLandmark
230 | GroupPowers.AllowRez
231 | GroupPowers.AllowSetHome
232 | GroupPowers.AllowVoiceChat
233 | GroupPowers.AssignMember
234 | GroupPowers.AssignMemberLimited
235 | GroupPowers.ChangeActions
236 | GroupPowers.ChangeIdentity
237 | GroupPowers.ChangeMedia
238 | GroupPowers.ChangeOptions
239 | GroupPowers.CreateRole
240 | GroupPowers.DeedObject
241 | GroupPowers.DeleteRole
242 | GroupPowers.Eject
243 | GroupPowers.FindPlaces
244 | GroupPowers.Invite
245 | GroupPowers.JoinChat
246 | GroupPowers.LandChangeIdentity
247 | GroupPowers.LandDeed
248 | GroupPowers.LandDivideJoin
249 | GroupPowers.LandEdit
250 | GroupPowers.LandEjectAndFreeze
251 | GroupPowers.LandGardening
252 | GroupPowers.LandManageAllowed
253 | GroupPowers.LandManageBanned
254 | GroupPowers.LandManagePasses
255 | GroupPowers.LandOptions
256 | GroupPowers.LandRelease
257 | GroupPowers.LandSetSale
258 | GroupPowers.ModerateChat
259 | GroupPowers.ObjectManipulate
260 | GroupPowers.ObjectSetForSale
261 | GroupPowers.ReceiveNotices
262 | GroupPowers.RemoveMember
263 | GroupPowers.ReturnGroupOwned
264 | GroupPowers.ReturnGroupSet
265 | GroupPowers.ReturnNonGroup
266 | GroupPowers.RoleProperties
267 | GroupPowers.SendNotices
268 | GroupPowers.SetLandingPoint
269 | GroupPowers.StartProposal
270 | GroupPowers.VoteOnProposal;
271 param["OwnersPowers"] = ((ulong)OwnerPowers).ToString();
272
273
274
275 274
276 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param); 275 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param);
277 276
@@ -612,8 +611,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
612 } 611 }
613 612
614 return Roles; 613 return Roles;
615
616
617 } 614 }
618 615
619 public List<GroupRolesData> GetGroupRoles(UUID requestingAgentID, UUID GroupID) 616 public List<GroupRolesData> GetGroupRoles(UUID requestingAgentID, UUID GroupID)
@@ -676,7 +673,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
676 } 673 }
677 674
678 return members; 675 return members;
679
680 } 676 }
681 677
682 public List<GroupRoleMembersData> GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID) 678 public List<GroupRoleMembersData> GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID)
@@ -727,9 +723,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
727 values.Add(data); 723 values.Add(data);
728 } 724 }
729 } 725 }
730 return values;
731 726
727 return values;
732 } 728 }
729
733 public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) 730 public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID)
734 { 731 {
735 Hashtable param = new Hashtable(); 732 Hashtable param = new Hashtable();
@@ -737,7 +734,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
737 734
738 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param); 735 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param);
739 736
740
741 if (respData.Contains("error")) 737 if (respData.Contains("error"))
742 { 738 {
743 return null; 739 return null;
@@ -761,6 +757,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
761 757
762 return data; 758 return data;
763 } 759 }
760
764 public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) 761 public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket)
765 { 762 {
766 string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, ""); 763 string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, "");
@@ -777,8 +774,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
777 XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param); 774 XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param);
778 } 775 }
779 776
780
781
782 #endregion 777 #endregion
783 778
784 #region GroupSessionTracking 779 #region GroupSessionTracking
diff --git a/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs b/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs
new file mode 100644
index 0000000..112ba4e
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs
@@ -0,0 +1,174 @@
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.Reflection;
31using OpenSim.Framework.Servers;
32using Mono.Addins;
33using log4net;
34using Nini.Config;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38using OpenSim.Framework.Servers.HttpServer;
39
40
41namespace OpenSim.Region.OptionalModules.WebSocketEchoModule
42{
43
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebSocketEchoModule")]
45 public class WebSocketEchoModule : ISharedRegionModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private bool enabled;
49 public string Name { get { return "WebSocketEchoModule"; } }
50
51 public Type ReplaceableInterface { get { return null; } }
52
53
54 private HashSet<WebSocketHttpServerHandler> _activeHandlers = new HashSet<WebSocketHttpServerHandler>();
55
56 public void Initialise(IConfigSource pConfig)
57 {
58 enabled =(pConfig.Configs["WebSocketEcho"] != null);
59 if (enabled)
60 m_log.DebugFormat("[WebSocketEchoModule]: INITIALIZED MODULE");
61 }
62
63 /// <summary>
64 /// This method sets up the callback to WebSocketHandlerCallback below when a HTTPRequest comes in for /echo
65 /// </summary>
66 public void PostInitialise()
67 {
68 if (enabled)
69 MainServer.Instance.AddWebSocketHandler("/echo", WebSocketHandlerCallback);
70 }
71
72 // This gets called by BaseHttpServer and gives us an opportunity to set things on the WebSocket handler before we turn it on
73 public void WebSocketHandlerCallback(string path, WebSocketHttpServerHandler handler)
74 {
75 SubscribeToEvents(handler);
76 handler.SetChunksize(8192);
77 handler.NoDelay_TCP_Nagle = true;
78 handler.HandshakeAndUpgrade();
79 }
80
81 //These are our normal events
82 public void SubscribeToEvents(WebSocketHttpServerHandler handler)
83 {
84 handler.OnClose += HandlerOnOnClose;
85 handler.OnText += HandlerOnOnText;
86 handler.OnUpgradeCompleted += HandlerOnOnUpgradeCompleted;
87 handler.OnData += HandlerOnOnData;
88 handler.OnPong += HandlerOnOnPong;
89 }
90
91 public void UnSubscribeToEvents(WebSocketHttpServerHandler handler)
92 {
93 handler.OnClose -= HandlerOnOnClose;
94 handler.OnText -= HandlerOnOnText;
95 handler.OnUpgradeCompleted -= HandlerOnOnUpgradeCompleted;
96 handler.OnData -= HandlerOnOnData;
97 handler.OnPong -= HandlerOnOnPong;
98 }
99
100 private void HandlerOnOnPong(object sender, PongEventArgs pongdata)
101 {
102 m_log.Info("[WebSocketEchoModule]: Got a pong.. ping time: " + pongdata.PingResponseMS);
103 }
104
105 private void HandlerOnOnData(object sender, WebsocketDataEventArgs data)
106 {
107 WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
108 obj.SendData(data.Data);
109 m_log.Info("[WebSocketEchoModule]: We received a bunch of ugly non-printable bytes");
110 obj.SendPingCheck();
111 }
112
113
114 private void HandlerOnOnUpgradeCompleted(object sender, UpgradeCompletedEventArgs completeddata)
115 {
116 WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
117 _activeHandlers.Add(obj);
118 }
119
120 private void HandlerOnOnText(object sender, WebsocketTextEventArgs text)
121 {
122 WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
123 obj.SendMessage(text.Data);
124 m_log.Info("[WebSocketEchoModule]: We received this: " + text.Data);
125 }
126
127 // Remove the references to our handler
128 private void HandlerOnOnClose(object sender, CloseEventArgs closedata)
129 {
130 WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
131 UnSubscribeToEvents(obj);
132
133 lock (_activeHandlers)
134 _activeHandlers.Remove(obj);
135 obj.Dispose();
136 }
137
138 // Shutting down.. so shut down all sockets.
139 // Note.. this should be done outside of an ienumerable if you're also hook to the close event.
140 public void Close()
141 {
142 if (!enabled)
143 return;
144
145 // We convert this to a for loop so we're not in in an IEnumerable when the close
146 //call triggers an event which then removes item from _activeHandlers that we're enumerating
147 WebSocketHttpServerHandler[] items = new WebSocketHttpServerHandler[_activeHandlers.Count];
148 _activeHandlers.CopyTo(items);
149
150 for (int i = 0; i < items.Length; i++)
151 {
152 items[i].Close(string.Empty);
153 items[i].Dispose();
154 }
155 _activeHandlers.Clear();
156 MainServer.Instance.RemoveWebSocketHandler("/echo");
157 }
158
159 public void AddRegion(Scene scene)
160 {
161 m_log.DebugFormat("[WebSocketEchoModule]: REGION {0} ADDED", scene.RegionInfo.RegionName);
162 }
163
164 public void RemoveRegion(Scene scene)
165 {
166 m_log.DebugFormat("[WebSocketEchoModule]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
167 }
168
169 public void RegionLoaded(Scene scene)
170 {
171 m_log.DebugFormat("[WebSocketEchoModule]: REGION {0} LOADED", scene.RegionInfo.RegionName);
172 }
173 }
174} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
index 40f7fbc..3083a33 100755
--- a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
+++ b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
@@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
146 { 146 {
147 foreach (PhysParameterEntry ppe in physScene.GetParameterList()) 147 foreach (PhysParameterEntry ppe in physScene.GetParameterList())
148 { 148 {
149 float val = 0.0f; 149 string val = string.Empty;
150 if (physScene.GetPhysicsParameter(ppe.name, out val)) 150 if (physScene.GetPhysicsParameter(ppe.name, out val))
151 { 151 {
152 WriteOut(" {0}/{1} = {2}", scene.RegionInfo.RegionName, ppe.name, val); 152 WriteOut(" {0}/{1} = {2}", scene.RegionInfo.RegionName, ppe.name, val);
@@ -159,7 +159,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
159 } 159 }
160 else 160 else
161 { 161 {
162 float val = 0.0f; 162 string val = string.Empty;
163 if (physScene.GetPhysicsParameter(parm, out val)) 163 if (physScene.GetPhysicsParameter(parm, out val))
164 { 164 {
165 WriteOut(" {0}/{1} = {2}", scene.RegionInfo.RegionName, parm, val); 165 WriteOut(" {0}/{1} = {2}", scene.RegionInfo.RegionName, parm, val);
@@ -185,21 +185,12 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
185 return; 185 return;
186 } 186 }
187 string parm = "xxx"; 187 string parm = "xxx";
188 float val = 0f; 188 string valparm = String.Empty;
189 uint localID = (uint)PhysParameterEntry.APPLY_TO_NONE; // set default value 189 uint localID = (uint)PhysParameterEntry.APPLY_TO_NONE; // set default value
190 try 190 try
191 { 191 {
192 parm = cmdparms[2]; 192 parm = cmdparms[2];
193 string valparm = cmdparms[3].ToLower(); 193 valparm = cmdparms[3].ToLower();
194 if (valparm == "true")
195 val = PhysParameterEntry.NUMERIC_TRUE;
196 else
197 {
198 if (valparm == "false")
199 val = PhysParameterEntry.NUMERIC_FALSE;
200 else
201 val = float.Parse(valparm, Culture.NumberFormatInfo);
202 }
203 if (cmdparms.Length > 4) 194 if (cmdparms.Length > 4)
204 { 195 {
205 if (cmdparms[4].ToLower() == "all") 196 if (cmdparms[4].ToLower() == "all")
@@ -224,7 +215,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
224 IPhysicsParameters physScene = scene.PhysicsScene as IPhysicsParameters; 215 IPhysicsParameters physScene = scene.PhysicsScene as IPhysicsParameters;
225 if (physScene != null) 216 if (physScene != null)
226 { 217 {
227 if (!physScene.SetPhysicsParameter(parm, val, localID)) 218 if (!physScene.SetPhysicsParameter(parm, valparm, localID))
228 { 219 {
229 WriteError("Failed set of parameter '{0}' for region '{1}'", parm, scene.RegionInfo.RegionName); 220 WriteError("Failed set of parameter '{0}' for region '{1}'", parm, scene.RegionInfo.RegionName);
230 } 221 }
diff --git a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
index 217b2d5..0065531 100644
--- a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.7.5.*")] 33[assembly: AssemblyVersion("0.7.6.*")]
34[assembly: AssemblyFileVersion("1.0.0.0")] 34[assembly: AssemblyFileVersion("1.0.0.0")]
35 35
36[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")] 36[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")]
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
index 34894ba..751e463 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
49 private static readonly ILog m_log = 49 private static readonly ILog m_log =
50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 private OSD m_ValueStore; 52 protected virtual OSD ValueStore { get; set; }
53 53
54 protected class TakeValueCallbackClass 54 protected class TakeValueCallbackClass
55 { 55 {
@@ -68,23 +68,58 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
68 protected List<TakeValueCallbackClass> m_TakeStore; 68 protected List<TakeValueCallbackClass> m_TakeStore;
69 protected List<TakeValueCallbackClass> m_ReadStore; 69 protected List<TakeValueCallbackClass> m_ReadStore;
70 70
71 // add separators for quoted paths
72 protected static Regex m_ParsePassOne = new Regex("{[^}]+}");
73
74 // add separators for array references
75 protected static Regex m_ParsePassTwo = new Regex("(\\[[0-9]+\\]|\\[\\+\\])");
76
77 // add quotes to bare identifiers which are limited to alphabetic characters
78 protected static Regex m_ParsePassThree = new Regex("\\.([a-zA-Z]+)");
79
80 // remove extra separator characters
81 protected static Regex m_ParsePassFour = new Regex("\\.+");
82
83 // expression used to validate the full path, this is canonical representation
84 protected static Regex m_ValidatePath = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$");
85
86 // expression used to match path components
87 protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)");
88
89 // extract the internals of an array reference
90 protected static Regex m_SimpleArrayPattern = new Regex("\\[([0-9]+)\\]");
91 protected static Regex m_ArrayPattern = new Regex("\\[([0-9]+|\\+)\\]");
92
93 // extract the internals of a has reference
94 protected static Regex m_HashPattern = new Regex("{([^}]+)}");
71 95
72 // ----------------------------------------------------------------- 96 // -----------------------------------------------------------------
73 /// <summary> 97 /// <summary>
74 /// 98 ///
75 /// </summary> 99 /// </summary>
76 // ----------------------------------------------------------------- 100 // -----------------------------------------------------------------
77 public JsonStore() : this("") {} 101 public static string CanonicalPathExpression(string path)
102 {
103 return PathExpressionToKey(ParsePathExpression(path));
104 }
78 105
79 public JsonStore(string value) 106 // -----------------------------------------------------------------
107 /// <summary>
108 ///
109 /// </summary>
110 // -----------------------------------------------------------------
111 public JsonStore()
80 { 112 {
81 m_TakeStore = new List<TakeValueCallbackClass>(); 113 m_TakeStore = new List<TakeValueCallbackClass>();
82 m_ReadStore = new List<TakeValueCallbackClass>(); 114 m_ReadStore = new List<TakeValueCallbackClass>();
83 115 }
116
117 public JsonStore(string value)
118 {
84 if (String.IsNullOrEmpty(value)) 119 if (String.IsNullOrEmpty(value))
85 m_ValueStore = new OSDMap(); 120 ValueStore = new OSDMap();
86 else 121 else
87 m_ValueStore = OSDParser.DeserializeJson(value); 122 ValueStore = OSDParser.DeserializeJson(value);
88 } 123 }
89 124
90 // ----------------------------------------------------------------- 125 // -----------------------------------------------------------------
@@ -95,7 +130,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
95 public bool TestPath(string expr, bool useJson) 130 public bool TestPath(string expr, bool useJson)
96 { 131 {
97 Stack<string> path = ParsePathExpression(expr); 132 Stack<string> path = ParsePathExpression(expr);
98 OSD result = ProcessPathExpression(m_ValueStore,path); 133 OSD result = ProcessPathExpression(ValueStore,path);
99 134
100 if (result == null) 135 if (result == null)
101 return false; 136 return false;
@@ -114,7 +149,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
114 public bool GetValue(string expr, out string value, bool useJson) 149 public bool GetValue(string expr, out string value, bool useJson)
115 { 150 {
116 Stack<string> path = ParsePathExpression(expr); 151 Stack<string> path = ParsePathExpression(expr);
117 OSD result = ProcessPathExpression(m_ValueStore,path); 152 OSD result = ProcessPathExpression(ValueStore,path);
118 return ConvertOutputValue(result,out value,useJson); 153 return ConvertOutputValue(result,out value,useJson);
119 } 154 }
120 155
@@ -150,7 +185,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
150 Stack<string> path = ParsePathExpression(expr); 185 Stack<string> path = ParsePathExpression(expr);
151 string pexpr = PathExpressionToKey(path); 186 string pexpr = PathExpressionToKey(path);
152 187
153 OSD result = ProcessPathExpression(m_ValueStore,path); 188 OSD result = ProcessPathExpression(ValueStore,path);
154 if (result == null) 189 if (result == null)
155 { 190 {
156 m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback)); 191 m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
@@ -181,7 +216,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
181 Stack<string> path = ParsePathExpression(expr); 216 Stack<string> path = ParsePathExpression(expr);
182 string pexpr = PathExpressionToKey(path); 217 string pexpr = PathExpressionToKey(path);
183 218
184 OSD result = ProcessPathExpression(m_ValueStore,path); 219 OSD result = ProcessPathExpression(ValueStore,path);
185 if (result == null) 220 if (result == null)
186 { 221 {
187 m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback)); 222 m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
@@ -211,7 +246,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
211 Stack<string> path = ParsePathExpression(expr); 246 Stack<string> path = ParsePathExpression(expr);
212 if (path.Count == 0) 247 if (path.Count == 0)
213 { 248 {
214 m_ValueStore = ovalue; 249 ValueStore = ovalue;
215 return true; 250 return true;
216 } 251 }
217 252
@@ -220,13 +255,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
220 if (pexpr != "") 255 if (pexpr != "")
221 pexpr += "."; 256 pexpr += ".";
222 257
223 OSD result = ProcessPathExpression(m_ValueStore,path); 258 OSD result = ProcessPathExpression(ValueStore,path);
224 if (result == null) 259 if (result == null)
225 return false; 260 return false;
226 261
227 Regex aPattern = new Regex("\\[([0-9]+|\\+)\\]"); 262 // Check for and extract array references
228 MatchCollection amatches = aPattern.Matches(pkey,0); 263 MatchCollection amatches = m_ArrayPattern.Matches(pkey,0);
229
230 if (amatches.Count > 0) 264 if (amatches.Count > 0)
231 { 265 {
232 if (result.Type != OSDType.Array) 266 if (result.Type != OSDType.Array)
@@ -263,9 +297,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
263 return false; 297 return false;
264 } 298 }
265 299
266 Regex hPattern = new Regex("{([^}]+)}"); 300 // Check for and extract hash references
267 MatchCollection hmatches = hPattern.Matches(pkey,0); 301 MatchCollection hmatches = m_HashPattern.Matches(pkey,0);
268
269 if (hmatches.Count > 0) 302 if (hmatches.Count > 0)
270 { 303 {
271 Match match = hmatches[0]; 304 Match match = hmatches[0];
@@ -340,26 +373,21 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
340 path = "." + path + "."; 373 path = "." + path + ".";
341 374
342 // add separators for quoted paths 375 // add separators for quoted paths
343 Regex pass1 = new Regex("{[^}]+}"); 376 path = m_ParsePassOne.Replace(path,".$0.",-1,0);
344 path = pass1.Replace(path,".$0.",-1,0);
345 377
346 // add separators for array references 378 // add separators for array references
347 Regex pass2 = new Regex("(\\[[0-9]+\\]|\\[\\+\\])"); 379 path = m_ParsePassTwo.Replace(path,".$0.",-1,0);
348 path = pass2.Replace(path,".$0.",-1,0);
349 380
350 // add quotes to bare identifier 381 // add quotes to bare identifier
351 Regex pass3 = new Regex("\\.([a-zA-Z]+)"); 382 path = m_ParsePassThree.Replace(path,".{$1}",-1,0);
352 path = pass3.Replace(path,".{$1}",-1,0);
353 383
354 // remove extra separators 384 // remove extra separators
355 Regex pass4 = new Regex("\\.+"); 385 path = m_ParsePassFour.Replace(path,".",-1,0);
356 path = pass4.Replace(path,".",-1,0);
357 386
358 Regex validate = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$"); 387 // validate the results (catches extra quote characters for example)
359 if (validate.IsMatch(path)) 388 if (m_ValidatePath.IsMatch(path))
360 { 389 {
361 Regex parser = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)"); 390 MatchCollection matches = m_PathComponent.Matches(path,0);
362 MatchCollection matches = parser.Matches(path,0);
363 foreach (Match match in matches) 391 foreach (Match match in matches)
364 m_path.Push(match.Groups[1].Value); 392 m_path.Push(match.Groups[1].Value);
365 } 393 }
@@ -385,9 +413,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
385 return null; 413 return null;
386 414
387 // ---------- Check for an array index ---------- 415 // ---------- Check for an array index ----------
388 Regex aPattern = new Regex("\\[([0-9]+)\\]"); 416 MatchCollection amatches = m_SimpleArrayPattern.Matches(pkey,0);
389 MatchCollection amatches = aPattern.Matches(pkey,0); 417
390
391 if (amatches.Count > 0) 418 if (amatches.Count > 0)
392 { 419 {
393 if (rmap.Type != OSDType.Array) 420 if (rmap.Type != OSDType.Array)
@@ -410,9 +437,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
410 } 437 }
411 438
412 // ---------- Check for a hash index ---------- 439 // ---------- Check for a hash index ----------
413 Regex hPattern = new Regex("{([^}]+)}"); 440 MatchCollection hmatches = m_HashPattern.Matches(pkey,0);
414 MatchCollection hmatches = hPattern.Matches(pkey,0); 441
415
416 if (hmatches.Count > 0) 442 if (hmatches.Count > 0)
417 { 443 {
418 if (rmap.Type != OSDType.Map) 444 if (rmap.Type != OSDType.Map)
@@ -497,4 +523,41 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
497 return pkey; 523 return pkey;
498 } 524 }
499 } 525 }
526
527 public class JsonObjectStore : JsonStore
528 {
529 private static readonly ILog m_log =
530 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
531
532 private Scene m_scene;
533 private UUID m_objectID;
534
535 protected override OSD ValueStore
536 {
537 get
538 {
539 SceneObjectPart sop = m_scene.GetSceneObjectPart(m_objectID);
540 if (sop == null)
541 {
542 // This is bad
543 return null;
544 }
545
546 return sop.DynAttrs.TopLevelMap;
547 }
548
549 // cannot set the top level
550 set
551 {
552 m_log.InfoFormat("[JsonStore] cannot set top level value in object store");
553 }
554 }
555
556 public JsonObjectStore(Scene scene, UUID oid) : base()
557 {
558 m_scene = scene;
559 m_objectID = oid;
560 }
561 }
562
500} 563}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
index e68764a..a36ef42 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -175,6 +175,34 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
175 /// 175 ///
176 /// </summary> 176 /// </summary>
177 // ----------------------------------------------------------------- 177 // -----------------------------------------------------------------
178 public bool AttachObjectStore(UUID objectID)
179 {
180 if (! m_enabled) return false;
181
182 SceneObjectPart sop = m_scene.GetSceneObjectPart(objectID);
183 if (sop == null)
184 {
185 m_log.InfoFormat("[JsonStore] unable to attach to unknown object; {0}",objectID);
186 return false;
187 }
188
189 lock (m_JsonValueStore)
190 {
191 if (m_JsonValueStore.ContainsKey(objectID))
192 return true;
193
194 JsonStore map = new JsonObjectStore(m_scene,objectID);
195 m_JsonValueStore.Add(objectID,map);
196 }
197
198 return true;
199 }
200
201 // -----------------------------------------------------------------
202 /// <summary>
203 ///
204 /// </summary>
205 // -----------------------------------------------------------------
178 public bool CreateStore(string value, ref UUID result) 206 public bool CreateStore(string value, ref UUID result)
179 { 207 {
180 if (result == UUID.Zero) 208 if (result == UUID.Zero)
@@ -221,6 +249,19 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
221 /// 249 ///
222 /// </summary> 250 /// </summary>
223 // ----------------------------------------------------------------- 251 // -----------------------------------------------------------------
252 public bool TestStore(UUID storeID)
253 {
254 if (! m_enabled) return false;
255
256 lock (m_JsonValueStore)
257 return m_JsonValueStore.ContainsKey(storeID);
258 }
259
260 // -----------------------------------------------------------------
261 /// <summary>
262 ///
263 /// </summary>
264 // -----------------------------------------------------------------
224 public bool TestPath(UUID storeID, string path, bool useJson) 265 public bool TestPath(UUID storeID, string path, bool useJson)
225 { 266 {
226 if (! m_enabled) return false; 267 if (! m_enabled) return false;
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
index 0c175ca..48b4a9f 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -39,6 +39,7 @@ using OpenMetaverse.StructuredData;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.Framework.Scenes.Scripting;
42using System.Collections.Generic; 43using System.Collections.Generic;
43using System.Text.RegularExpressions; 44using System.Text.RegularExpressions;
44 45
@@ -92,12 +93,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
92 } 93 }
93 catch (Exception e) 94 catch (Exception e)
94 { 95 {
95 m_log.ErrorFormat("[JsonStoreScripts] initialization error: {0}",e.Message); 96 m_log.ErrorFormat("[JsonStoreScripts]: initialization error: {0}", e.Message);
96 return; 97 return;
97 } 98 }
98 99
99 if (m_enabled) 100 if (m_enabled)
100 m_log.DebugFormat("[JsonStoreScripts] module is enabled"); 101 m_log.DebugFormat("[JsonStoreScripts]: module is enabled");
101 } 102 }
102 103
103 // ----------------------------------------------------------------- 104 // -----------------------------------------------------------------
@@ -150,7 +151,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
150 m_comms = m_scene.RequestModuleInterface<IScriptModuleComms>(); 151 m_comms = m_scene.RequestModuleInterface<IScriptModuleComms>();
151 if (m_comms == null) 152 if (m_comms == null)
152 { 153 {
153 m_log.ErrorFormat("[JsonStoreScripts] ScriptModuleComms interface not defined"); 154 m_log.ErrorFormat("[JsonStoreScripts]: ScriptModuleComms interface not defined");
154 m_enabled = false; 155 m_enabled = false;
155 return; 156 return;
156 } 157 }
@@ -158,40 +159,45 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
158 m_store = m_scene.RequestModuleInterface<IJsonStoreModule>(); 159 m_store = m_scene.RequestModuleInterface<IJsonStoreModule>();
159 if (m_store == null) 160 if (m_store == null)
160 { 161 {
161 m_log.ErrorFormat("[JsonStoreScripts] JsonModule interface not defined"); 162 m_log.ErrorFormat("[JsonStoreScripts]: JsonModule interface not defined");
162 m_enabled = false; 163 m_enabled = false;
163 return; 164 return;
164 } 165 }
165 166
166 try 167 try
167 { 168 {
168 m_comms.RegisterScriptInvocation(this,"JsonCreateStore"); 169 m_comms.RegisterScriptInvocations(this);
169 m_comms.RegisterScriptInvocation(this,"JsonDestroyStore"); 170
171 // m_comms.RegisterScriptInvocation(this, "JsonCreateStore");
172 // m_comms.RegisterScriptInvocation(this, "JsonAttachObjectStore");
173 // m_comms.RegisterScriptInvocation(this, "JsonDestroyStore");
174 // m_comms.RegisterScriptInvocation(this, "JsonTestStore");
170 175
171 m_comms.RegisterScriptInvocation(this,"JsonReadNotecard"); 176 // m_comms.RegisterScriptInvocation(this, "JsonReadNotecard");
172 m_comms.RegisterScriptInvocation(this,"JsonWriteNotecard"); 177 // m_comms.RegisterScriptInvocation(this, "JsonWriteNotecard");
173 178
174 m_comms.RegisterScriptInvocation(this,"JsonTestPath"); 179 // m_comms.RegisterScriptInvocation(this, "JsonTestPathList");
175 m_comms.RegisterScriptInvocation(this,"JsonTestPathJson"); 180 // m_comms.RegisterScriptInvocation(this, "JsonTestPath");
181 // m_comms.RegisterScriptInvocation(this, "JsonTestPathJson");
176 182
177 m_comms.RegisterScriptInvocation(this,"JsonGetValue"); 183 // m_comms.RegisterScriptInvocation(this, "JsonGetValue");
178 m_comms.RegisterScriptInvocation(this,"JsonGetValueJson"); 184 // m_comms.RegisterScriptInvocation(this, "JsonGetValueJson");
179 185
180 m_comms.RegisterScriptInvocation(this,"JsonTakeValue"); 186 // m_comms.RegisterScriptInvocation(this, "JsonTakeValue");
181 m_comms.RegisterScriptInvocation(this,"JsonTakeValueJson"); 187 // m_comms.RegisterScriptInvocation(this, "JsonTakeValueJson");
182 188
183 m_comms.RegisterScriptInvocation(this,"JsonReadValue"); 189 // m_comms.RegisterScriptInvocation(this, "JsonReadValue");
184 m_comms.RegisterScriptInvocation(this,"JsonReadValueJson"); 190 // m_comms.RegisterScriptInvocation(this, "JsonReadValueJson");
185 191
186 m_comms.RegisterScriptInvocation(this,"JsonSetValue"); 192 // m_comms.RegisterScriptInvocation(this, "JsonSetValue");
187 m_comms.RegisterScriptInvocation(this,"JsonSetValueJson"); 193 // m_comms.RegisterScriptInvocation(this, "JsonSetValueJson");
188 194
189 m_comms.RegisterScriptInvocation(this,"JsonRemoveValue"); 195 // m_comms.RegisterScriptInvocation(this, "JsonRemoveValue");
190 } 196 }
191 catch (Exception e) 197 catch (Exception e)
192 { 198 {
193 // See http://opensimulator.org/mantis/view.php?id=5971 for more information 199 // See http://opensimulator.org/mantis/view.php?id=5971 for more information
194 m_log.WarnFormat("[JsonStroreScripts] script method registration failed; {0}",e.Message); 200 m_log.WarnFormat("[JsonStoreScripts]: script method registration failed; {0}", e.Message);
195 m_enabled = false; 201 m_enabled = false;
196 } 202 }
197 } 203 }
@@ -214,17 +220,23 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
214 /// 220 ///
215 /// </summary> 221 /// </summary>
216 // ----------------------------------------------------------------- 222 // -----------------------------------------------------------------
217 protected void GenerateRuntimeError(string msg) 223 [ScriptInvocation]
224 public UUID JsonAttachObjectStore(UUID hostID, UUID scriptID)
218 { 225 {
219 throw new Exception("JsonStore Runtime Error: " + msg); 226 UUID uuid = UUID.Zero;
227 if (! m_store.AttachObjectStore(hostID))
228 GenerateRuntimeError("Failed to create Json store");
229
230 return hostID;
220 } 231 }
221 232
222 // ----------------------------------------------------------------- 233 // -----------------------------------------------------------------
223 /// <summary> 234 /// <summary>
224 /// 235 ///
225 /// </summary> 236 /// </summary>
226 // ----------------------------------------------------------------- 237 // -----------------------------------------------------------------
227 protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) 238 [ScriptInvocation]
239 public UUID JsonCreateStore(UUID hostID, UUID scriptID, string value)
228 { 240 {
229 UUID uuid = UUID.Zero; 241 UUID uuid = UUID.Zero;
230 if (! m_store.CreateStore(value, ref uuid)) 242 if (! m_store.CreateStore(value, ref uuid))
@@ -238,7 +250,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
238 /// 250 ///
239 /// </summary> 251 /// </summary>
240 // ----------------------------------------------------------------- 252 // -----------------------------------------------------------------
241 protected int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID) 253 [ScriptInvocation]
254 public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID)
242 { 255 {
243 return m_store.DestroyStore(storeID) ? 1 : 0; 256 return m_store.DestroyStore(storeID) ? 1 : 0;
244 } 257 }
@@ -248,10 +261,22 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
248 /// 261 ///
249 /// </summary> 262 /// </summary>
250 // ----------------------------------------------------------------- 263 // -----------------------------------------------------------------
251 protected UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID) 264 [ScriptInvocation]
265 public int JsonTestStore(UUID hostID, UUID scriptID, UUID storeID)
266 {
267 return m_store.TestStore(storeID) ? 1 : 0;
268 }
269
270 // -----------------------------------------------------------------
271 /// <summary>
272 ///
273 /// </summary>
274 // -----------------------------------------------------------------
275 [ScriptInvocation]
276 public UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string notecardIdentifier)
252 { 277 {
253 UUID reqID = UUID.Random(); 278 UUID reqID = UUID.Random();
254 Util.FireAndForget(delegate(object o) { DoJsonReadNotecard(reqID,hostID,scriptID,storeID,path,assetID); }); 279 Util.FireAndForget(o => DoJsonReadNotecard(reqID, hostID, scriptID, storeID, path, notecardIdentifier));
255 return reqID; 280 return reqID;
256 } 281 }
257 282
@@ -260,7 +285,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
260 /// 285 ///
261 /// </summary> 286 /// </summary>
262 // ----------------------------------------------------------------- 287 // -----------------------------------------------------------------
263 protected UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name) 288 [ScriptInvocation]
289 public UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name)
264 { 290 {
265 UUID reqID = UUID.Random(); 291 UUID reqID = UUID.Random();
266 Util.FireAndForget(delegate(object o) { DoJsonWriteNotecard(reqID,hostID,scriptID,storeID,path,name); }); 292 Util.FireAndForget(delegate(object o) { DoJsonWriteNotecard(reqID,hostID,scriptID,storeID,path,name); });
@@ -272,12 +298,25 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
272 /// 298 ///
273 /// </summary> 299 /// </summary>
274 // ----------------------------------------------------------------- 300 // -----------------------------------------------------------------
275 protected int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path) 301 [ScriptInvocation]
302 public string JsonList2Path(UUID hostID, UUID scriptID, object[] pathlist)
303 {
304 return JsonStore.CanonicalPathExpression(ConvertList2Path(pathlist));
305 }
306
307 // -----------------------------------------------------------------
308 /// <summary>
309 ///
310 /// </summary>
311 // -----------------------------------------------------------------
312 [ScriptInvocation]
313 public int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
276 { 314 {
277 return m_store.TestPath(storeID,path,false) ? 1 : 0; 315 return m_store.TestPath(storeID,path,false) ? 1 : 0;
278 } 316 }
279 317
280 protected int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path) 318 [ScriptInvocation]
319 public int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path)
281 { 320 {
282 return m_store.TestPath(storeID,path,true) ? 1 : 0; 321 return m_store.TestPath(storeID,path,true) ? 1 : 0;
283 } 322 }
@@ -287,12 +326,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
287 /// 326 ///
288 /// </summary> 327 /// </summary>
289 // ----------------------------------------------------------------- 328 // -----------------------------------------------------------------
290 protected int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value) 329 [ScriptInvocation]
330 public int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
291 { 331 {
292 return m_store.SetValue(storeID,path,value,false) ? 1 : 0; 332 return m_store.SetValue(storeID,path,value,false) ? 1 : 0;
293 } 333 }
294 334
295 protected int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value) 335 [ScriptInvocation]
336 public int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
296 { 337 {
297 return m_store.SetValue(storeID,path,value,true) ? 1 : 0; 338 return m_store.SetValue(storeID,path,value,true) ? 1 : 0;
298 } 339 }
@@ -302,7 +343,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
302 /// 343 ///
303 /// </summary> 344 /// </summary>
304 // ----------------------------------------------------------------- 345 // -----------------------------------------------------------------
305 protected int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path) 346 [ScriptInvocation]
347 public int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path)
306 { 348 {
307 return m_store.RemoveValue(storeID,path) ? 1 : 0; 349 return m_store.RemoveValue(storeID,path) ? 1 : 0;
308 } 350 }
@@ -312,14 +354,16 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
312 /// 354 ///
313 /// </summary> 355 /// </summary>
314 // ----------------------------------------------------------------- 356 // -----------------------------------------------------------------
315 protected string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path) 357 [ScriptInvocation]
358 public string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path)
316 { 359 {
317 string value = String.Empty; 360 string value = String.Empty;
318 m_store.GetValue(storeID,path,false,out value); 361 m_store.GetValue(storeID,path,false,out value);
319 return value; 362 return value;
320 } 363 }
321 364
322 protected string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) 365 [ScriptInvocation]
366 public string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
323 { 367 {
324 string value = String.Empty; 368 string value = String.Empty;
325 m_store.GetValue(storeID,path,true, out value); 369 m_store.GetValue(storeID,path,true, out value);
@@ -331,80 +375,104 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
331 /// 375 ///
332 /// </summary> 376 /// </summary>
333 // ----------------------------------------------------------------- 377 // -----------------------------------------------------------------
334 protected UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path) 378 [ScriptInvocation]
379 public UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path)
335 { 380 {
336 UUID reqID = UUID.Random(); 381 UUID reqID = UUID.Random();
337 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,false); }); 382 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,false); });
338 return reqID; 383 return reqID;
339 } 384 }
340 385
341 protected UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) 386 [ScriptInvocation]
387 public UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
342 { 388 {
343 UUID reqID = UUID.Random(); 389 UUID reqID = UUID.Random();
344 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,true); }); 390 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,true); });
345 return reqID; 391 return reqID;
346 } 392 }
347 393
348 private void DoJsonTakeValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
349 {
350 try
351 {
352 m_store.TakeValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
353 return;
354 }
355 catch (Exception e)
356 {
357 m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString());
358 }
359
360 DispatchValue(scriptID,reqID,String.Empty);
361 }
362
363
364 // ----------------------------------------------------------------- 394 // -----------------------------------------------------------------
365 /// <summary> 395 /// <summary>
366 /// 396 ///
367 /// </summary> 397 /// </summary>
368 // ----------------------------------------------------------------- 398 // -----------------------------------------------------------------
369 protected UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path) 399 [ScriptInvocation]
400 public UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path)
370 { 401 {
371 UUID reqID = UUID.Random(); 402 UUID reqID = UUID.Random();
372 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,false); }); 403 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,false); });
373 return reqID; 404 return reqID;
374 } 405 }
375 406
376 protected UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) 407 [ScriptInvocation]
408 public UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
377 { 409 {
378 UUID reqID = UUID.Random(); 410 UUID reqID = UUID.Random();
379 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,true); }); 411 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,true); });
380 return reqID; 412 return reqID;
381 } 413 }
382 414
383 private void DoJsonReadValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson) 415#endregion
416
417 // -----------------------------------------------------------------
418 /// <summary>
419 ///
420 /// </summary>
421 // -----------------------------------------------------------------
422 protected void GenerateRuntimeError(string msg)
423 {
424 throw new Exception("JsonStore Runtime Error: " + msg);
425 }
426
427 // -----------------------------------------------------------------
428 /// <summary>
429 ///
430 /// </summary>
431 // -----------------------------------------------------------------
432 protected void DispatchValue(UUID scriptID, UUID reqID, string value)
433 {
434 m_comms.DispatchReply(scriptID,1,value,reqID.ToString());
435 }
436
437 // -----------------------------------------------------------------
438 /// <summary>
439 ///
440 /// </summary>
441 // -----------------------------------------------------------------
442 private void DoJsonTakeValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
384 { 443 {
385 try 444 try
386 { 445 {
387 m_store.ReadValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); }); 446 m_store.TakeValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
388 return; 447 return;
389 } 448 }
390 catch (Exception e) 449 catch (Exception e)
391 { 450 {
392 m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString()); 451 m_log.InfoFormat("[JsonStoreScripts]: unable to retrieve value; {0}",e.ToString());
393 } 452 }
394 453
395 DispatchValue(scriptID,reqID,String.Empty); 454 DispatchValue(scriptID,reqID,String.Empty);
396 } 455 }
397 456
398#endregion
399 457
400 // ----------------------------------------------------------------- 458 // -----------------------------------------------------------------
401 /// <summary> 459 /// <summary>
402 /// 460 ///
403 /// </summary> 461 /// </summary>
404 // ----------------------------------------------------------------- 462 // -----------------------------------------------------------------
405 protected void DispatchValue(UUID scriptID, UUID reqID, string value) 463 private void DoJsonReadValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
406 { 464 {
407 m_comms.DispatchReply(scriptID,1,value,reqID.ToString()); 465 try
466 {
467 m_store.ReadValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
468 return;
469 }
470 catch (Exception e)
471 {
472 m_log.InfoFormat("[JsonStoreScripts]: unable to retrieve value; {0}",e.ToString());
473 }
474
475 DispatchValue(scriptID,reqID,String.Empty);
408 } 476 }
409 477
410 // ----------------------------------------------------------------- 478 // -----------------------------------------------------------------
@@ -412,16 +480,25 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
412 /// 480 ///
413 /// </summary> 481 /// </summary>
414 // ----------------------------------------------------------------- 482 // -----------------------------------------------------------------
415 private void DoJsonReadNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID) 483 private void DoJsonReadNotecard(
484 UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, string notecardIdentifier)
416 { 485 {
486 UUID assetID;
487
488 if (!UUID.TryParse(notecardIdentifier, out assetID))
489 {
490 SceneObjectPart part = m_scene.GetSceneObjectPart(hostID);
491 assetID = ScriptUtils.GetAssetIdFromItemName(part, notecardIdentifier, (int)AssetType.Notecard);
492 }
493
417 AssetBase a = m_scene.AssetService.Get(assetID.ToString()); 494 AssetBase a = m_scene.AssetService.Get(assetID.ToString());
418 if (a == null) 495 if (a == null)
419 GenerateRuntimeError(String.Format("Unable to find notecard asset {0}",assetID)); 496 GenerateRuntimeError(String.Format("Unable to find notecard asset {0}", assetID));
420 497
421 if (a.Type != (sbyte)AssetType.Notecard) 498 if (a.Type != (sbyte)AssetType.Notecard)
422 GenerateRuntimeError(String.Format("Invalid notecard asset {0}",assetID)); 499 GenerateRuntimeError(String.Format("Invalid notecard asset {0}", assetID));
423 500
424 m_log.DebugFormat("[JsonStoreScripts] read notecard in context {0}",storeID); 501 m_log.DebugFormat("[JsonStoreScripts]: read notecard in context {0}",storeID);
425 502
426 try 503 try
427 { 504 {
@@ -432,11 +509,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
432 } 509 }
433 catch (Exception e) 510 catch (Exception e)
434 { 511 {
435 m_log.WarnFormat("[JsonStoreScripts] Json parsing failed; {0}",e.Message); 512 m_log.WarnFormat("[JsonStoreScripts]: Json parsing failed; {0}", e.Message);
436 } 513 }
437 514
438 GenerateRuntimeError(String.Format("Json parsing failed for {0}",assetID.ToString())); 515 GenerateRuntimeError(String.Format("Json parsing failed for {0}", assetID));
439 m_comms.DispatchReply(scriptID,0,"",reqID.ToString()); 516 m_comms.DispatchReply(scriptID, 0, "", reqID.ToString());
440 } 517 }
441 518
442 // ----------------------------------------------------------------- 519 // -----------------------------------------------------------------
@@ -494,5 +571,43 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
494 571
495 m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString()); 572 m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString());
496 } 573 }
574
575 // -----------------------------------------------------------------
576 /// <summary>
577 /// Convert a list of values that are path components to a single string path
578 /// </summary>
579 // -----------------------------------------------------------------
580 protected static Regex m_ArrayPattern = new Regex("^([0-9]+|\\+)$");
581 private string ConvertList2Path(object[] pathlist)
582 {
583 string path = "";
584 for (int i = 0; i < pathlist.Length; i++)
585 {
586 string token = "";
587
588 if (pathlist[i] is string)
589 {
590 token = pathlist[i].ToString();
591
592 // Check to see if this is a bare number which would not be a valid
593 // identifier otherwise
594 if (m_ArrayPattern.IsMatch(token))
595 token = '[' + token + ']';
596 }
597 else if (pathlist[i] is int)
598 {
599 token = "[" + pathlist[i].ToString() + "]";
600 }
601 else
602 {
603 token = "." + pathlist[i].ToString() + ".";
604 }
605
606 path += token + ".";
607 }
608
609 return path;
610 }
611
497 } 612 }
498} 613} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
new file mode 100644
index 0000000..98b5624
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
@@ -0,0 +1,257 @@
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.Reflection;
31using System.Text;
32using log4net;
33using Nini.Config;
34using NUnit.Framework;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.Scripting.ScriptModuleComms;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.ScriptEngine.Shared;
40using OpenSim.Region.ScriptEngine.Shared.Api;
41using OpenSim.Services.Interfaces;
42using OpenSim.Tests.Common;
43using OpenSim.Tests.Common.Mock;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
46{
47 /// <summary>
48 /// Tests for inventory functions in LSL
49 /// </summary>
50 [TestFixture]
51 public class JsonStoreScriptModuleTests : OpenSimTestCase
52 {
53 private Scene m_scene;
54 private MockScriptEngine m_engine;
55 private ScriptModuleCommsModule m_smcm;
56
57 [TestFixtureSetUp]
58 public void FixtureInit()
59 {
60 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
61 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
62 }
63
64 [TestFixtureTearDown]
65 public void TearDown()
66 {
67 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
68 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
69 // tests really shouldn't).
70 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
71 }
72
73 [SetUp]
74 public override void SetUp()
75 {
76 base.SetUp();
77
78 IConfigSource configSource = new IniConfigSource();
79 IConfig jsonStoreConfig = configSource.AddConfig("JsonStore");
80 jsonStoreConfig.Set("Enabled", "true");
81
82 m_engine = new MockScriptEngine();
83 m_smcm = new ScriptModuleCommsModule();
84 JsonStoreModule jsm = new JsonStoreModule();
85 JsonStoreScriptModule jssm = new JsonStoreScriptModule();
86
87 m_scene = new SceneHelpers().SetupScene();
88 SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, jssm);
89
90 try
91 {
92 m_smcm.RegisterScriptInvocation(this, "DummyTestMethod");
93 }
94 catch (ArgumentException)
95 {
96 Assert.Ignore("Ignoring test since running on .NET 3.5 or earlier.");
97 }
98
99 // XXX: Unfortunately, ICommsModule currently has no way of deregistering methods.
100 }
101
102 private object InvokeOp(string name, params object[] args)
103 {
104 return InvokeOpOnHost(name, UUID.Zero, args);
105 }
106
107 private object InvokeOpOnHost(string name, UUID hostId, params object[] args)
108 {
109 return m_smcm.InvokeOperation(hostId, UUID.Zero, name, args);
110 }
111
112 [Test]
113 public void TestJsonCreateStore()
114 {
115 TestHelpers.InMethod();
116// TestHelpers.EnableLogging();
117
118 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
119 Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
120 }
121
122 [Test]
123 public void TestJsonDestroyStore()
124 {
125 TestHelpers.InMethod();
126// TestHelpers.EnableLogging();
127
128 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
129 int dsrv = (int)InvokeOp("JsonDestroyStore", storeId);
130
131 Assert.That(dsrv, Is.EqualTo(1));
132
133 int tprv = (int)InvokeOp("JsonTestPath", storeId, "Hello");
134 Assert.That(tprv, Is.EqualTo(0));
135 }
136
137 [Test]
138 public void TestJsonGetValue()
139 {
140 TestHelpers.InMethod();
141// TestHelpers.EnableLogging();
142
143 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
144
145 string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
146 Assert.That(value, Is.EqualTo("World"));
147 }
148
149// [Test]
150// public void TestJsonTakeValue()
151// {
152// TestHelpers.InMethod();
153//// TestHelpers.EnableLogging();
154//
155// UUID storeId
156// = (UUID)m_smcm.InvokeOperation(
157// UUID.Zero, UUID.Zero, "JsonCreateStore", new object[] { "{ 'Hello' : 'World' }" });
158//
159// string value
160// = (string)m_smcm.InvokeOperation(
161// UUID.Zero, UUID.Zero, "JsonTakeValue", new object[] { storeId, "Hello" });
162//
163// Assert.That(value, Is.EqualTo("World"));
164//
165// string value2
166// = (string)m_smcm.InvokeOperation(
167// UUID.Zero, UUID.Zero, "JsonGetValue", new object[] { storeId, "Hello" });
168//
169// Assert.That(value, Is.Null);
170// }
171
172 [Test]
173 public void TestJsonRemoveValue()
174 {
175 TestHelpers.InMethod();
176// TestHelpers.EnableLogging();
177
178 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
179
180 int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
181 Assert.That(returnValue, Is.EqualTo(1));
182
183 int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
184 Assert.That(result, Is.EqualTo(0));
185
186 string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
187 Assert.That(returnValue2, Is.EqualTo(""));
188 }
189
190 [Test]
191 public void TestJsonTestPath()
192 {
193 TestHelpers.InMethod();
194// TestHelpers.EnableLogging();
195
196 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
197
198 int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
199 Assert.That(result, Is.EqualTo(1));
200 }
201
202 [Test]
203 public void TestJsonSetValue()
204 {
205 TestHelpers.InMethod();
206// TestHelpers.EnableLogging();
207
208 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
209
210 int result = (int)InvokeOp("JsonSetValue", storeId, "Hello", "World");
211 Assert.That(result, Is.EqualTo(1));
212
213 string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
214 Assert.That(value, Is.EqualTo("World"));
215 }
216
217 /// <summary>
218 /// Test for reading and writing json to a notecard
219 /// </summary>
220 /// <remarks>
221 /// TODO: Really needs to test correct receipt of the link_message event. Could do this by directly fetching
222 /// it via the MockScriptEngine or perhaps by a dummy script instance.
223 /// </remarks>
224 [Test]
225 public void TestJsonWriteReadNotecard()
226 {
227 TestHelpers.InMethod();
228 TestHelpers.EnableLogging();
229
230 string notecardName = "nc1";
231
232 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1));
233 m_scene.AddSceneObject(so);
234
235 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello':'World' }");
236
237 // Write notecard
238 UUID writeNotecardRequestId = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, storeId, "/", notecardName);
239 Assert.That(writeNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
240
241 TaskInventoryItem nc1Item = so.RootPart.Inventory.GetInventoryItem(notecardName);
242 Assert.That(nc1Item, Is.Not.Null);
243
244 // TODO: Should probably independently check the contents.
245
246 // Read notecard
247 UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello':'World' }");
248 UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "/", notecardName);
249 Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
250
251 string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
252 Assert.That(value, Is.EqualTo("World"));
253 }
254
255 public object DummyTestMethod(object o1, object o2, object o3, object o4, object o5) { return null; }
256 }
257} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
index 6120a81..709d389 100644
--- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
@@ -46,6 +46,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
46{ 46{
47 public class XmlRpcInfo 47 public class XmlRpcInfo
48 { 48 {
49 public UUID item;
49 public UUID channel; 50 public UUID channel;
50 public string uri; 51 public string uri;
51 } 52 }
@@ -88,6 +89,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
88 return; 89 return;
89 90
90 scene.RegisterModuleInterface<IXmlRpcRouter>(this); 91 scene.RegisterModuleInterface<IXmlRpcRouter>(this);
92
93 IScriptModule scriptEngine = scene.RequestModuleInterface<IScriptModule>();
94 if ( scriptEngine != null )
95 {
96 scriptEngine.OnScriptRemoved += this.ScriptRemoved;
97 scriptEngine.OnObjectRemoved += this.ObjectRemoved;
98
99 }
91 } 100 }
92 101
93 public void RegionLoaded(Scene scene) 102 public void RegionLoaded(Scene scene)
@@ -120,22 +129,36 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
120 129
121 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri) 130 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri)
122 { 131 {
123 if (!m_Channels.ContainsKey(itemID)) 132 if (!m_Enabled)
124 { 133 return;
125 XmlRpcInfo info = new XmlRpcInfo();
126 info.channel = channel;
127 info.uri = uri;
128 134
129 bool success = SynchronousRestObjectRequester.MakeRequest<XmlRpcInfo, bool>( 135 m_log.InfoFormat("[XMLRPC GRID ROUTER]: New receiver Obj: {0} Ch: {1} ID: {2} URI: {3}",
130 "POST", m_ServerURI+"/RegisterChannel/", info); 136 objectID.ToString(), channel.ToString(), itemID.ToString(), uri);
131 137
132 if (!success) 138 XmlRpcInfo info = new XmlRpcInfo();
133 { 139 info.channel = channel;
134 m_log.Error("[XMLRPC GRID ROUTER] Error contacting server"); 140 info.uri = uri;
135 } 141 info.item = itemID;
142
143 bool success = SynchronousRestObjectRequester.MakeRequest<XmlRpcInfo, bool>(
144 "POST", m_ServerURI+"/RegisterChannel/", info);
136 145
137 m_Channels[itemID] = channel; 146 if (!success)
147 {
148 m_log.Error("[XMLRPC GRID ROUTER] Error contacting server");
138 } 149 }
150
151 m_Channels[itemID] = channel;
152
153 }
154
155 public void UnRegisterReceiver(string channelID, UUID itemID)
156 {
157 if (!m_Enabled)
158 return;
159
160 RemoveChannel(itemID);
161
139 } 162 }
140 163
141 public void ScriptRemoved(UUID itemID) 164 public void ScriptRemoved(UUID itemID)
@@ -143,10 +166,33 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
143 if (!m_Enabled) 166 if (!m_Enabled)
144 return; 167 return;
145 168
146 if (m_Channels.ContainsKey(itemID)) 169 RemoveChannel(itemID);
170
171 }
172
173 public void ObjectRemoved(UUID objectID)
174 {
175 // m_log.InfoFormat("[XMLRPC GRID ROUTER]: Object Removed {0}",objectID.ToString());
176 }
177
178 private bool RemoveChannel(UUID itemID)
179 {
180 if(!m_Channels.ContainsKey(itemID))
181 {
182 m_log.InfoFormat("[XMLRPC GRID ROUTER]: Attempted to unregister non-existing Item: {0}", itemID.ToString());
183 return false;
184 }
185
186 XmlRpcInfo info = new XmlRpcInfo();
187
188 info.channel = m_Channels[itemID];
189 info.item = itemID;
190 info.uri = "http://0.0.0.0:00";
191
192 if (info != null)
147 { 193 {
148 bool success = SynchronousRestObjectRequester.MakeRequest<UUID, bool>( 194 bool success = SynchronousRestObjectRequester.MakeRequest<XmlRpcInfo, bool>(
149 "POST", m_ServerURI+"/RemoveChannel/", m_Channels[itemID]); 195 "POST", m_ServerURI+"/RemoveChannel/", info);
150 196
151 if (!success) 197 if (!success)
152 { 198 {
@@ -154,11 +200,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
154 } 200 }
155 201
156 m_Channels.Remove(itemID); 202 m_Channels.Remove(itemID);
203 return true;
157 } 204 }
158 } 205 return false;
159
160 public void ObjectRemoved(UUID objectID)
161 {
162 } 206 }
163 } 207 }
164} 208}
diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
index 4bde52a..32549d6 100644
--- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
@@ -104,12 +104,18 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule
104 } 104 }
105 } 105 }
106 106
107 public void UnRegisterReceiver(string channelID, UUID itemID)
108 {
109 }
110
107 public void ScriptRemoved(UUID itemID) 111 public void ScriptRemoved(UUID itemID)
108 { 112 {
113 // System.Console.WriteLine("TEST Script Removed!");
109 } 114 }
110 115
111 public void ObjectRemoved(UUID objectID) 116 public void ObjectRemoved(UUID objectID)
112 { 117 {
118 // System.Console.WriteLine("TEST Obj Removed!");
113 } 119 }
114 } 120 }
115} 121}
diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
index c7e3a7a..57d9217 100644
--- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
+++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
49 /// (such as land transfers). There is no money code here! Use FORGE as an example for money code. 49 /// (such as land transfers). There is no money code here! Use FORGE as an example for money code.
50 /// Demo Economy/Money Module. This is a purposely crippled module! 50 /// Demo Economy/Money Module. This is a purposely crippled module!
51 /// // To land transfer you need to add: 51 /// // To land transfer you need to add:
52 /// -helperuri <ADDRESS TO THIS SERVER> 52 /// -helperuri http://serveraddress:port/
53 /// to the command line parameters you use to start up your client 53 /// to the command line parameters you use to start up your client
54 /// This commonly looks like -helperuri http://127.0.0.1:9000/ 54 /// This commonly looks like -helperuri http://127.0.0.1:9000/
55 /// 55 ///
@@ -116,10 +116,9 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
116 } 116 }
117 117
118 /// <summary> 118 /// <summary>
119 /// Startup 119 /// Called on startup so the module can be configured.
120 /// </summary> 120 /// </summary>
121 /// <param name="scene"></param> 121 /// <param name="config">Configuration source.</param>
122 /// <param name="config"></param>
123 public void Initialise(IConfigSource config) 122 public void Initialise(IConfigSource config)
124 { 123 {
125 m_gConfig = config; 124 m_gConfig = config;
@@ -674,9 +673,12 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
674 } 673 }
675 674
676 /// <summary> 675 /// <summary>
677 /// When the client closes the connection we remove their accounting info from memory to free up resources. 676 /// When the client closes the connection we remove their accounting
677 /// info from memory to free up resources.
678 /// </summary> 678 /// </summary>
679 /// <param name="AgentID"></param> 679 /// <param name="AgentID">UUID of agent</param>
680 /// <param name="scene">Scene the agent was connected to.</param>
681 /// <see cref="OpenSim.Region.Framework.Scenes.EventManager.ClientClosed"/>
680 public void ClientClosed(UUID AgentID, Scene scene) 682 public void ClientClosed(UUID AgentID, Scene scene)
681 { 683 {
682 684
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index ef4005b..34362af 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -48,7 +48,7 @@ using OpenSim.Tests.Common.Mock;
48namespace OpenSim.Region.OptionalModules.World.NPC.Tests 48namespace OpenSim.Region.OptionalModules.World.NPC.Tests
49{ 49{
50 [TestFixture] 50 [TestFixture]
51 public class NPCModuleTests 51 public class NPCModuleTests : OpenSimTestCase
52 { 52 {
53 private TestScene m_scene; 53 private TestScene m_scene;
54 private AvatarFactoryModule m_afMod; 54 private AvatarFactoryModule m_afMod;
@@ -74,6 +74,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
74 [SetUp] 74 [SetUp]
75 public void Init() 75 public void Init()
76 { 76 {
77 base.SetUp();
78
77 IConfigSource config = new IniConfigSource(); 79 IConfigSource config = new IniConfigSource();
78 config.AddConfig("NPC"); 80 config.AddConfig("NPC");
79 config.Configs["NPC"].Set("Enabled", "true"); 81 config.Configs["NPC"].Set("Enabled", "true");
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
new file mode 100644
index 0000000..5fb74b0
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
@@ -0,0 +1,235 @@
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 System.Text;
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Framework.Console;
39using OpenSim.Framework.Monitoring;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42
43namespace OpenSim.Region.OptionalModules.Avatar.Attachments
44{
45 /// <summary>
46 /// A module that just holds commands for inspecting avatar appearance.
47 /// </summary>
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SceneCommandsModule")]
49 public class SceneCommandsModule : ISceneCommandsModule, INonSharedRegionModule
50 {
51// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 private Scene m_scene;
54
55 public string Name { get { return "Scene Commands Module"; } }
56
57 public Type ReplaceableInterface { get { return null; } }
58
59 public void Initialise(IConfigSource source)
60 {
61// m_log.DebugFormat("[SCENE COMMANDS MODULE]: INITIALIZED MODULE");
62 }
63
64 public void PostInitialise()
65 {
66// m_log.DebugFormat("[SCENE COMMANDS MODULE]: POST INITIALIZED MODULE");
67 }
68
69 public void Close()
70 {
71// m_log.DebugFormat("[SCENE COMMANDS MODULE]: CLOSED MODULE");
72 }
73
74 public void AddRegion(Scene scene)
75 {
76// m_log.DebugFormat("[SCENE COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
77
78 m_scene = scene;
79
80 m_scene.RegisterModuleInterface<ISceneCommandsModule>(this);
81 }
82
83 public void RemoveRegion(Scene scene)
84 {
85// m_log.DebugFormat("[SCENE COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
86 }
87
88 public void RegionLoaded(Scene scene)
89 {
90// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
91
92 scene.AddCommand(
93 "Debug", this, "debug scene get",
94 "debug scene get",
95 "List current scene options.",
96 "If active is false then main scene update and maintenance loops are suspended.\n"
97 + "If animations is true then extra animations debug information is logged.\n"
98 + "If collisions is false then collisions with other objects are turned off.\n"
99 + "If pbackup is false then periodic scene backup is turned off.\n"
100 + "If physics is false then all physics objects are non-physical.\n"
101 + "If scripting is false then no scripting operations happen.\n"
102 + "If teleport is true then some extra teleport debug information is logged.\n"
103 + "If updates is true then any frame which exceeds double the maximum desired frame time is logged.",
104 HandleDebugSceneGetCommand);
105
106 scene.AddCommand(
107 "Debug", this, "debug scene set",
108 "debug scene set active|collisions|pbackup|physics|scripting|teleport|updates true|false",
109 "Turn on scene debugging options.",
110 "If active is false then main scene update and maintenance loops are suspended.\n"
111 + "If animations is true then extra animations debug information is logged.\n"
112 + "If collisions is false then collisions with other objects are turned off.\n"
113 + "If pbackup is false then periodic scene backup is turned off.\n"
114 + "If physics is false then all physics objects are non-physical.\n"
115 + "If scripting is false then no scripting operations happen.\n"
116 + "If teleport is true then some extra teleport debug information is logged.\n"
117 + "If updates is true then any frame which exceeds double the maximum desired frame time is logged.",
118 HandleDebugSceneSetCommand);
119 }
120
121 private void HandleDebugSceneGetCommand(string module, string[] args)
122 {
123 if (args.Length == 3)
124 {
125 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
126 return;
127
128 OutputSceneDebugOptions();
129 }
130 else
131 {
132 MainConsole.Instance.Output("Usage: debug scene get");
133 }
134 }
135
136 private void OutputSceneDebugOptions()
137 {
138 ConsoleDisplayList cdl = new ConsoleDisplayList();
139 cdl.AddRow("active", m_scene.Active);
140 cdl.AddRow("animations", m_scene.DebugAnimations);
141 cdl.AddRow("pbackup", m_scene.PeriodicBackup);
142 cdl.AddRow("physics", m_scene.PhysicsEnabled);
143 cdl.AddRow("scripting", m_scene.ScriptsEnabled);
144 cdl.AddRow("teleport", m_scene.DebugTeleporting);
145 cdl.AddRow("updates", m_scene.DebugUpdates);
146
147 MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name);
148 MainConsole.Instance.Output(cdl.ToString());
149 }
150
151 private void HandleDebugSceneSetCommand(string module, string[] args)
152 {
153 if (args.Length == 5)
154 {
155 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
156 return;
157
158 string key = args[3];
159 string value = args[4];
160 SetSceneDebugOptions(new Dictionary<string, string>() { { key, value } });
161
162 MainConsole.Instance.OutputFormat("Set {0} debug scene {1} = {2}", m_scene.Name, key, value);
163 }
164 else
165 {
166 MainConsole.Instance.Output(
167 "Usage: debug scene set active|collisions|pbackup|physics|scripting|teleport|updates true|false");
168 }
169 }
170
171 public void SetSceneDebugOptions(Dictionary<string, string> options)
172 {
173 if (options.ContainsKey("active"))
174 {
175 bool active;
176
177 if (bool.TryParse(options["active"], out active))
178 m_scene.Active = active;
179 }
180
181 if (options.ContainsKey("animations"))
182 {
183 bool active;
184
185 if (bool.TryParse(options["animations"], out active))
186 m_scene.DebugAnimations = active;
187 }
188
189 if (options.ContainsKey("pbackup"))
190 {
191 bool active;
192
193 if (bool.TryParse(options["pbackup"], out active))
194 m_scene.PeriodicBackup = active;
195 }
196
197 if (options.ContainsKey("scripting"))
198 {
199 bool enableScripts = true;
200 if (bool.TryParse(options["scripting"], out enableScripts))
201 m_scene.ScriptsEnabled = enableScripts;
202 }
203
204 if (options.ContainsKey("physics"))
205 {
206 bool enablePhysics;
207 if (bool.TryParse(options["physics"], out enablePhysics))
208 m_scene.PhysicsEnabled = enablePhysics;
209 }
210
211// if (options.ContainsKey("collisions"))
212// {
213// // TODO: Implement. If false, should stop objects colliding, though possibly should still allow
214// // the avatar themselves to collide with the ground.
215// }
216
217 if (options.ContainsKey("teleport"))
218 {
219 bool enableTeleportDebugging;
220 if (bool.TryParse(options["teleport"], out enableTeleportDebugging))
221 m_scene.DebugTeleporting = enableTeleportDebugging;
222 }
223
224 if (options.ContainsKey("updates"))
225 {
226 bool enableUpdateDebugging;
227 if (bool.TryParse(options["updates"], out enableUpdateDebugging))
228 {
229 m_scene.DebugUpdates = enableUpdateDebugging;
230 GcNotify.Enabled = enableUpdateDebugging;
231 }
232 }
233 }
234 }
235} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
index fb9cb66..6fd6f7e 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.5.*")] 58[assembly : AssemblyVersion("0.7.6.*")]
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
index 7ab2a03..373c7e0 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
49 49
50 public PhysicsScene GetScene(string sceneIdentifier) 50 public PhysicsScene GetScene(string sceneIdentifier)
51 { 51 {
52 return new BasicScene(sceneIdentifier); 52 return new BasicScene(GetName(), sceneIdentifier);
53 } 53 }
54 54
55 public string GetName() 55 public string GetName()
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
index f5826ed..c4b9117 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
@@ -49,8 +49,10 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
49 49
50 //protected internal string sceneIdentifier; 50 //protected internal string sceneIdentifier;
51 51
52 public BasicScene(string _sceneIdentifier) 52 public BasicScene(string engineType, string _sceneIdentifier)
53 { 53 {
54 EngineType = engineType;
55 Name = EngineType + "/" + _sceneIdentifier;
54 //sceneIdentifier = _sceneIdentifier; 56 //sceneIdentifier = _sceneIdentifier;
55 } 57 }
56 58
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
new file mode 100755
index 0000000..ae54499
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -0,0 +1,1885 @@
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.Reflection;
30using System.Runtime.InteropServices;
31using System.Security;
32using System.Text;
33
34using OpenSim.Framework;
35
36using OpenMetaverse;
37
38namespace OpenSim.Region.Physics.BulletSPlugin
39{
40public sealed class BSAPIUnman : BSAPITemplate
41{
42
43private sealed class BulletWorldUnman : BulletWorld
44{
45 public IntPtr ptr;
46 public BulletWorldUnman(uint id, BSScene physScene, IntPtr xx)
47 : base(id, physScene)
48 {
49 ptr = xx;
50 }
51}
52
53private sealed class BulletBodyUnman : BulletBody
54{
55 public IntPtr ptr;
56 public BulletBodyUnman(uint id, IntPtr xx)
57 : base(id)
58 {
59 ptr = xx;
60 }
61 public override bool HasPhysicalBody
62 {
63 get { return ptr != IntPtr.Zero; }
64 }
65 public override void Clear()
66 {
67 ptr = IntPtr.Zero;
68 }
69 public override string AddrString
70 {
71 get { return ptr.ToString("X"); }
72 }
73}
74
75private sealed class BulletShapeUnman : BulletShape
76{
77 public IntPtr ptr;
78 public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ)
79 : base()
80 {
81 ptr = xx;
82 type = typ;
83 }
84 public override bool HasPhysicalShape
85 {
86 get { return ptr != IntPtr.Zero; }
87 }
88 public override void Clear()
89 {
90 ptr = IntPtr.Zero;
91 }
92 public override BulletShape Clone()
93 {
94 return new BulletShapeUnman(ptr, type);
95 }
96 public override bool ReferenceSame(BulletShape other)
97 {
98 BulletShapeUnman otheru = other as BulletShapeUnman;
99 return (otheru != null) && (this.ptr == otheru.ptr);
100
101 }
102 public override string AddrString
103 {
104 get { return ptr.ToString("X"); }
105 }
106}
107private sealed class BulletConstraintUnman : BulletConstraint
108{
109 public BulletConstraintUnman(IntPtr xx) : base()
110 {
111 ptr = xx;
112 }
113 public IntPtr ptr;
114
115 public override void Clear()
116 {
117 ptr = IntPtr.Zero;
118 }
119 public override bool HasPhysicalConstraint { get { return ptr != IntPtr.Zero; } }
120
121 // Used for log messages for a unique display of the memory/object allocated to this instance
122 public override string AddrString
123 {
124 get { return ptr.ToString("X"); }
125 }
126}
127
128// We pin the memory passed between the managed and unmanaged code.
129GCHandle m_paramsHandle;
130private GCHandle m_collisionArrayPinnedHandle;
131private GCHandle m_updateArrayPinnedHandle;
132
133// Handle to the callback used by the unmanaged code to call into the managed code.
134// Used for debug logging.
135// Need to store the handle in a persistant variable so it won't be freed.
136private BSAPICPP.DebugLogCallback m_DebugLogCallbackHandle;
137
138private BSScene PhysicsScene { get; set; }
139
140public override string BulletEngineName { get { return "BulletUnmanaged"; } }
141public override string BulletEngineVersion { get; protected set; }
142
143public BSAPIUnman(string paramName, BSScene physScene)
144{
145 PhysicsScene = physScene;
146
147 // Do something fancy with the paramName to get the right DLL implementation
148 // like "Bullet-2.80-OpenCL-Intel" loading the version for Intel based OpenCL implementation, etc.
149 if (Util.IsWindows())
150 Util.LoadArchSpecificWindowsDll("BulletSim.dll");
151 // If not Windows, loading is performed by the
152 // Mono loader as specified in
153 // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config".
154}
155
156// Initialization and simulation
157public override BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
158 int maxCollisions, ref CollisionDesc[] collisionArray,
159 int maxUpdates, ref EntityProperties[] updateArray
160 )
161{
162 // Pin down the memory that will be used to pass object collisions and updates back from unmanaged code
163 m_paramsHandle = GCHandle.Alloc(parms, GCHandleType.Pinned);
164 m_collisionArrayPinnedHandle = GCHandle.Alloc(collisionArray, GCHandleType.Pinned);
165 m_updateArrayPinnedHandle = GCHandle.Alloc(updateArray, GCHandleType.Pinned);
166
167 // If Debug logging level, enable logging from the unmanaged code
168 m_DebugLogCallbackHandle = null;
169 if (BSScene.m_log.IsDebugEnabled && PhysicsScene.PhysicsLogging.Enabled)
170 {
171 BSScene.m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", BSScene.LogHeader);
172 if (PhysicsScene.PhysicsLogging.Enabled)
173 // The handle is saved in a variable to make sure it doesn't get freed after this call
174 m_DebugLogCallbackHandle = new BSAPICPP.DebugLogCallback(BulletLoggerPhysLog);
175 else
176 m_DebugLogCallbackHandle = new BSAPICPP.DebugLogCallback(BulletLogger);
177 }
178
179 // Get the version of the DLL
180 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
181 // BulletEngineVersion = BulletSimAPI.GetVersion2();
182 BulletEngineVersion = "";
183
184 // Call the unmanaged code with the buffers and other information
185 return new BulletWorldUnman(0, PhysicsScene, BSAPICPP.Initialize2(maxPosition, m_paramsHandle.AddrOfPinnedObject(),
186 maxCollisions, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
187 maxUpdates, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
188 m_DebugLogCallbackHandle));
189
190}
191
192// Called directly from unmanaged code so don't do much
193private void BulletLogger(string msg)
194{
195 BSScene.m_log.Debug("[BULLETS UNMANAGED]:" + msg);
196}
197
198// Called directly from unmanaged code so don't do much
199private void BulletLoggerPhysLog(string msg)
200{
201 PhysicsScene.DetailLog("[BULLETS UNMANAGED]:" + msg);
202}
203
204public override int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
205 out int updatedEntityCount, out int collidersCount)
206{
207 BulletWorldUnman worldu = world as BulletWorldUnman;
208 return BSAPICPP.PhysicsStep2(worldu.ptr, timeStep, maxSubSteps, fixedTimeStep, out updatedEntityCount, out collidersCount);
209}
210
211public override void Shutdown(BulletWorld world)
212{
213 BulletWorldUnman worldu = world as BulletWorldUnman;
214 BSAPICPP.Shutdown2(worldu.ptr);
215
216 if (m_paramsHandle.IsAllocated)
217 {
218 m_paramsHandle.Free();
219 }
220 if (m_collisionArrayPinnedHandle.IsAllocated)
221 {
222 m_collisionArrayPinnedHandle.Free();
223 }
224 if (m_updateArrayPinnedHandle.IsAllocated)
225 {
226 m_updateArrayPinnedHandle.Free();
227 }
228}
229
230public override bool PushUpdate(BulletBody obj)
231{
232 BulletBodyUnman bodyu = obj as BulletBodyUnman;
233 return BSAPICPP.PushUpdate2(bodyu.ptr);
234}
235
236public override bool UpdateParameter(BulletWorld world, uint localID, String parm, float value)
237{
238 BulletWorldUnman worldu = world as BulletWorldUnman;
239 return BSAPICPP.UpdateParameter2(worldu.ptr, localID, parm, value);
240}
241
242// =====================================================================================
243// Mesh, hull, shape and body creation helper routines
244public override BulletShape CreateMeshShape(BulletWorld world,
245 int indicesCount, int[] indices,
246 int verticesCount, float[] vertices)
247{
248 BulletWorldUnman worldu = world as BulletWorldUnman;
249 return new BulletShapeUnman(
250 BSAPICPP.CreateMeshShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices),
251 BSPhysicsShapeType.SHAPE_MESH);
252}
253
254public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls)
255{
256 BulletWorldUnman worldu = world as BulletWorldUnman;
257 return new BulletShapeUnman(
258 BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls),
259 BSPhysicsShapeType.SHAPE_HULL);
260}
261
262public override BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
263{
264 BulletWorldUnman worldu = world as BulletWorldUnman;
265 BulletShapeUnman shapeu = meshShape as BulletShapeUnman;
266 return new BulletShapeUnman(
267 BSAPICPP.BuildHullShapeFromMesh2(worldu.ptr, shapeu.ptr),
268 BSPhysicsShapeType.SHAPE_HULL);
269}
270
271public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData)
272{
273 BulletWorldUnman worldu = world as BulletWorldUnman;
274 return new BulletShapeUnman(BSAPICPP.BuildNativeShape2(worldu.ptr, shapeData), shapeData.Type);
275}
276
277public override bool IsNativeShape(BulletShape shape)
278{
279 BulletShapeUnman shapeu = shape as BulletShapeUnman;
280 if (shapeu != null && shapeu.HasPhysicalShape)
281 return BSAPICPP.IsNativeShape2(shapeu.ptr);
282 return false;
283}
284
285public override void SetShapeCollisionMargin(BulletShape shape, float margin)
286{
287 BulletShapeUnman shapeu = shape as BulletShapeUnman;
288 if (shapeu != null && shapeu.HasPhysicalShape)
289 BSAPICPP.SetShapeCollisionMargin2(shapeu.ptr, margin);
290}
291
292public override BulletShape BuildCapsuleShape(BulletWorld world, float radius, float height, Vector3 scale)
293{
294 BulletWorldUnman worldu = world as BulletWorldUnman;
295 return new BulletShapeUnman(
296 BSAPICPP.BuildCapsuleShape2(worldu.ptr, radius, height, scale),
297 BSPhysicsShapeType.SHAPE_CAPSULE);
298}
299
300public override BulletShape CreateCompoundShape(BulletWorld world, bool enableDynamicAabbTree)
301{
302 BulletWorldUnman worldu = world as BulletWorldUnman;
303 return new BulletShapeUnman(
304 BSAPICPP.CreateCompoundShape2(worldu.ptr, enableDynamicAabbTree),
305 BSPhysicsShapeType.SHAPE_COMPOUND);
306
307}
308
309public override int GetNumberOfCompoundChildren(BulletShape shape)
310{
311 BulletShapeUnman shapeu = shape as BulletShapeUnman;
312 if (shapeu != null && shapeu.HasPhysicalShape)
313 return BSAPICPP.GetNumberOfCompoundChildren2(shapeu.ptr);
314 return 0;
315}
316
317public override void AddChildShapeToCompoundShape(BulletShape shape, BulletShape addShape, Vector3 pos, Quaternion rot)
318{
319 BulletShapeUnman shapeu = shape as BulletShapeUnman;
320 BulletShapeUnman addShapeu = addShape as BulletShapeUnman;
321 BSAPICPP.AddChildShapeToCompoundShape2(shapeu.ptr, addShapeu.ptr, pos, rot);
322}
323
324public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape shape, int indx)
325{
326 BulletShapeUnman shapeu = shape as BulletShapeUnman;
327 return new BulletShapeUnman(BSAPICPP.GetChildShapeFromCompoundShapeIndex2(shapeu.ptr, indx), BSPhysicsShapeType.SHAPE_UNKNOWN);
328}
329
330public override BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape shape, int indx)
331{
332 BulletShapeUnman shapeu = shape as BulletShapeUnman;
333 return new BulletShapeUnman(BSAPICPP.RemoveChildShapeFromCompoundShapeIndex2(shapeu.ptr, indx), BSPhysicsShapeType.SHAPE_UNKNOWN);
334}
335
336public override void RemoveChildShapeFromCompoundShape(BulletShape shape, BulletShape removeShape)
337{
338 BulletShapeUnman shapeu = shape as BulletShapeUnman;
339 BulletShapeUnman removeShapeu = removeShape as BulletShapeUnman;
340 BSAPICPP.RemoveChildShapeFromCompoundShape2(shapeu.ptr, removeShapeu.ptr);
341}
342
343public override void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb)
344{
345 BulletShapeUnman shapeu = pShape as BulletShapeUnman;
346 BSAPICPP.UpdateChildTransform2(shapeu.ptr, childIndex, pos, rot, shouldRecalculateLocalAabb);
347}
348
349public override void RecalculateCompoundShapeLocalAabb(BulletShape shape)
350{
351 BulletShapeUnman shapeu = shape as BulletShapeUnman;
352 BSAPICPP.RecalculateCompoundShapeLocalAabb2(shapeu.ptr);
353}
354
355public override BulletShape DuplicateCollisionShape(BulletWorld world, BulletShape srcShape, uint id)
356{
357 BulletWorldUnman worldu = world as BulletWorldUnman;
358 BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman;
359 return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.type);
360}
361
362public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape)
363{
364 BulletWorldUnman worldu = world as BulletWorldUnman;
365 BulletShapeUnman shapeu = shape as BulletShapeUnman;
366 return BSAPICPP.DeleteCollisionShape2(worldu.ptr, shapeu.ptr);
367}
368
369public override CollisionObjectTypes GetBodyType(BulletBody obj)
370{
371 BulletBodyUnman bodyu = obj as BulletBodyUnman;
372 return (CollisionObjectTypes)BSAPICPP.GetBodyType2(bodyu.ptr);
373}
374
375public override BulletBody CreateBodyFromShape(BulletWorld world, BulletShape shape, uint id, Vector3 pos, Quaternion rot)
376{
377 BulletWorldUnman worldu = world as BulletWorldUnman;
378 BulletShapeUnman shapeu = shape as BulletShapeUnman;
379 return new BulletBodyUnman(id, BSAPICPP.CreateBodyFromShape2(worldu.ptr, shapeu.ptr, id, pos, rot));
380}
381
382public override BulletBody CreateBodyWithDefaultMotionState(BulletShape shape, uint id, Vector3 pos, Quaternion rot)
383{
384 BulletShapeUnman shapeu = shape as BulletShapeUnman;
385 return new BulletBodyUnman(id, BSAPICPP.CreateBodyWithDefaultMotionState2(shapeu.ptr, id, pos, rot));
386}
387
388public override BulletBody CreateGhostFromShape(BulletWorld world, BulletShape shape, uint id, Vector3 pos, Quaternion rot)
389{
390 BulletWorldUnman worldu = world as BulletWorldUnman;
391 BulletShapeUnman shapeu = shape as BulletShapeUnman;
392 return new BulletBodyUnman(id, BSAPICPP.CreateGhostFromShape2(worldu.ptr, shapeu.ptr, id, pos, rot));
393}
394
395public override void DestroyObject(BulletWorld world, BulletBody obj)
396{
397 BulletWorldUnman worldu = world as BulletWorldUnman;
398 BulletBodyUnman bodyu = obj as BulletBodyUnman;
399 BSAPICPP.DestroyObject2(worldu.ptr, bodyu.ptr);
400}
401
402// =====================================================================================
403// Terrain creation and helper routines
404public override BulletShape CreateGroundPlaneShape(uint id, float height, float collisionMargin)
405{
406 return new BulletShapeUnman(BSAPICPP.CreateGroundPlaneShape2(id, height, collisionMargin), BSPhysicsShapeType.SHAPE_GROUNDPLANE);
407}
408
409public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
410 float scaleFactor, float collisionMargin)
411{
412 return new BulletShapeUnman(BSAPICPP.CreateTerrainShape2(id, size, minHeight, maxHeight, heightMap, scaleFactor, collisionMargin),
413 BSPhysicsShapeType.SHAPE_TERRAIN);
414}
415
416// =====================================================================================
417// Constraint creation and helper routines
418public override BulletConstraint Create6DofConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
419 Vector3 frame1loc, Quaternion frame1rot,
420 Vector3 frame2loc, Quaternion frame2rot,
421 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
422{
423 BulletWorldUnman worldu = world as BulletWorldUnman;
424 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
425 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
426 return new BulletConstraintUnman(BSAPICPP.Create6DofConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, frame1loc, frame1rot,
427 frame2loc, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
428}
429
430public override BulletConstraint Create6DofConstraintToPoint(BulletWorld world, BulletBody obj1, BulletBody obj2,
431 Vector3 joinPoint,
432 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
433{
434 BulletWorldUnman worldu = world as BulletWorldUnman;
435 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
436 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
437 return new BulletConstraintUnman(BSAPICPP.Create6DofConstraintToPoint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr,
438 joinPoint, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
439}
440
441public override BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
442 Vector3 pivotinA, Vector3 pivotinB,
443 Vector3 axisInA, Vector3 axisInB,
444 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
445{
446 BulletWorldUnman worldu = world as BulletWorldUnman;
447 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
448 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
449 return new BulletConstraintUnman(BSAPICPP.CreateHingeConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr,
450 pivotinA, pivotinB, axisInA, axisInB, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
451}
452
453public override void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse)
454{
455 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
456 BSAPICPP.SetConstraintEnable2(constrainu.ptr, numericTrueFalse);
457}
458
459public override void SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations)
460{
461 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
462 BSAPICPP.SetConstraintNumSolverIterations2(constrainu.ptr, iterations);
463}
464
465public override bool SetFrames(BulletConstraint constrain,
466 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
467{
468 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
469 return BSAPICPP.SetFrames2(constrainu.ptr, frameA, frameArot, frameB, frameBrot);
470}
471
472public override bool SetLinearLimits(BulletConstraint constrain, Vector3 low, Vector3 hi)
473{
474 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
475 return BSAPICPP.SetLinearLimits2(constrainu.ptr, low, hi);
476}
477
478public override bool SetAngularLimits(BulletConstraint constrain, Vector3 low, Vector3 hi)
479{
480 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
481 return BSAPICPP.SetAngularLimits2(constrainu.ptr, low, hi);
482}
483
484public override bool UseFrameOffset(BulletConstraint constrain, float enable)
485{
486 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
487 return BSAPICPP.UseFrameOffset2(constrainu.ptr, enable);
488}
489
490public override bool TranslationalLimitMotor(BulletConstraint constrain, float enable, float targetVel, float maxMotorForce)
491{
492 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
493 return BSAPICPP.TranslationalLimitMotor2(constrainu.ptr, enable, targetVel, maxMotorForce);
494}
495
496public override bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold)
497{
498 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
499 return BSAPICPP.SetBreakingImpulseThreshold2(constrainu.ptr, threshold);
500}
501
502public override bool CalculateTransforms(BulletConstraint constrain)
503{
504 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
505 return BSAPICPP.CalculateTransforms2(constrainu.ptr);
506}
507
508public override bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis)
509{
510 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
511 return BSAPICPP.SetConstraintParam2(constrainu.ptr, paramIndex, value, axis);
512}
513
514public override bool DestroyConstraint(BulletWorld world, BulletConstraint constrain)
515{
516 BulletWorldUnman worldu = world as BulletWorldUnman;
517 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
518 return BSAPICPP.DestroyConstraint2(worldu.ptr, constrainu.ptr);
519}
520
521// =====================================================================================
522// btCollisionWorld entries
523public override void UpdateSingleAabb(BulletWorld world, BulletBody obj)
524{
525 BulletWorldUnman worldu = world as BulletWorldUnman;
526 BulletBodyUnman bodyu = obj as BulletBodyUnman;
527 BSAPICPP.UpdateSingleAabb2(worldu.ptr, bodyu.ptr);
528}
529
530public override void UpdateAabbs(BulletWorld world)
531{
532 BulletWorldUnman worldu = world as BulletWorldUnman;
533 BSAPICPP.UpdateAabbs2(worldu.ptr);
534}
535
536public override bool GetForceUpdateAllAabbs(BulletWorld world)
537{
538 BulletWorldUnman worldu = world as BulletWorldUnman;
539 return BSAPICPP.GetForceUpdateAllAabbs2(worldu.ptr);
540}
541
542public override void SetForceUpdateAllAabbs(BulletWorld world, bool force)
543{
544 BulletWorldUnman worldu = world as BulletWorldUnman;
545 BSAPICPP.SetForceUpdateAllAabbs2(worldu.ptr, force);
546}
547
548// =====================================================================================
549// btDynamicsWorld entries
550public override bool AddObjectToWorld(BulletWorld world, BulletBody obj)
551{
552 BulletWorldUnman worldu = world as BulletWorldUnman;
553 BulletBodyUnman bodyu = obj as BulletBodyUnman;
554
555 // Bullet resets several variables when an object is added to the world.
556 // Gravity is reset to world default depending on the static/dynamic
557 // type. Of course, the collision flags in the broadphase proxy are initialized to default.
558 Vector3 origGrav = BSAPICPP.GetGravity2(bodyu.ptr);
559
560 bool ret = BSAPICPP.AddObjectToWorld2(worldu.ptr, bodyu.ptr);
561
562 if (ret)
563 {
564 BSAPICPP.SetGravity2(bodyu.ptr, origGrav);
565 obj.ApplyCollisionMask(world.physicsScene);
566 }
567 return ret;
568}
569
570public override bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj)
571{
572 BulletWorldUnman worldu = world as BulletWorldUnman;
573 BulletBodyUnman bodyu = obj as BulletBodyUnman;
574 return BSAPICPP.RemoveObjectFromWorld2(worldu.ptr, bodyu.ptr);
575}
576
577public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects)
578{
579 BulletWorldUnman worldu = world as BulletWorldUnman;
580 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
581 return BSAPICPP.AddConstraintToWorld2(worldu.ptr, constrainu.ptr, disableCollisionsBetweenLinkedObjects);
582}
583
584public override bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain)
585{
586 BulletWorldUnman worldu = world as BulletWorldUnman;
587 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
588 return BSAPICPP.RemoveConstraintFromWorld2(worldu.ptr, constrainu.ptr);
589}
590// =====================================================================================
591// btCollisionObject entries
592public override Vector3 GetAnisotripicFriction(BulletConstraint constrain)
593{
594 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
595 return BSAPICPP.GetAnisotripicFriction2(constrainu.ptr);
596}
597
598public override Vector3 SetAnisotripicFriction(BulletConstraint constrain, Vector3 frict)
599{
600 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
601 return BSAPICPP.SetAnisotripicFriction2(constrainu.ptr, frict);
602}
603
604public override bool HasAnisotripicFriction(BulletConstraint constrain)
605{
606 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
607 return BSAPICPP.HasAnisotripicFriction2(constrainu.ptr);
608}
609
610public override void SetContactProcessingThreshold(BulletBody obj, float val)
611{
612 BulletBodyUnman bodyu = obj as BulletBodyUnman;
613 BSAPICPP.SetContactProcessingThreshold2(bodyu.ptr, val);
614}
615
616public override float GetContactProcessingThreshold(BulletBody obj)
617{
618 BulletBodyUnman bodyu = obj as BulletBodyUnman;
619 return BSAPICPP.GetContactProcessingThreshold2(bodyu.ptr);
620}
621
622public override bool IsStaticObject(BulletBody obj)
623{
624 BulletBodyUnman bodyu = obj as BulletBodyUnman;
625 return BSAPICPP.IsStaticObject2(bodyu.ptr);
626}
627
628public override bool IsKinematicObject(BulletBody obj)
629{
630 BulletBodyUnman bodyu = obj as BulletBodyUnman;
631 return BSAPICPP.IsKinematicObject2(bodyu.ptr);
632}
633
634public override bool IsStaticOrKinematicObject(BulletBody obj)
635{
636 BulletBodyUnman bodyu = obj as BulletBodyUnman;
637 return BSAPICPP.IsStaticOrKinematicObject2(bodyu.ptr);
638}
639
640public override bool HasContactResponse(BulletBody obj)
641{
642 BulletBodyUnman bodyu = obj as BulletBodyUnman;
643 return BSAPICPP.HasContactResponse2(bodyu.ptr);
644}
645
646public override void SetCollisionShape(BulletWorld world, BulletBody obj, BulletShape shape)
647{
648 BulletWorldUnman worldu = world as BulletWorldUnman;
649 BulletBodyUnman bodyu = obj as BulletBodyUnman;
650 BulletShapeUnman shapeu = shape as BulletShapeUnman;
651 if (worldu != null && bodyu != null)
652 {
653 // Special case to allow the caller to zero out the reference to any physical shape
654 if (shapeu != null)
655 BSAPICPP.SetCollisionShape2(worldu.ptr, bodyu.ptr, shapeu.ptr);
656 else
657 BSAPICPP.SetCollisionShape2(worldu.ptr, bodyu.ptr, IntPtr.Zero);
658 }
659}
660
661public override BulletShape GetCollisionShape(BulletBody obj)
662{
663 BulletBodyUnman bodyu = obj as BulletBodyUnman;
664 return new BulletShapeUnman(BSAPICPP.GetCollisionShape2(bodyu.ptr), BSPhysicsShapeType.SHAPE_UNKNOWN);
665}
666
667public override int GetActivationState(BulletBody obj)
668{
669 BulletBodyUnman bodyu = obj as BulletBodyUnman;
670 return BSAPICPP.GetActivationState2(bodyu.ptr);
671}
672
673public override void SetActivationState(BulletBody obj, int state)
674{
675 BulletBodyUnman bodyu = obj as BulletBodyUnman;
676 BSAPICPP.SetActivationState2(bodyu.ptr, state);
677}
678
679public override void SetDeactivationTime(BulletBody obj, float dtime)
680{
681 BulletBodyUnman bodyu = obj as BulletBodyUnman;
682 BSAPICPP.SetDeactivationTime2(bodyu.ptr, dtime);
683}
684
685public override float GetDeactivationTime(BulletBody obj)
686{
687 BulletBodyUnman bodyu = obj as BulletBodyUnman;
688 return BSAPICPP.GetDeactivationTime2(bodyu.ptr);
689}
690
691public override void ForceActivationState(BulletBody obj, ActivationState state)
692{
693 BulletBodyUnman bodyu = obj as BulletBodyUnman;
694 BSAPICPP.ForceActivationState2(bodyu.ptr, state);
695}
696
697public override void Activate(BulletBody obj, bool forceActivation)
698{
699 BulletBodyUnman bodyu = obj as BulletBodyUnman;
700 BSAPICPP.Activate2(bodyu.ptr, forceActivation);
701}
702
703public override bool IsActive(BulletBody obj)
704{
705 BulletBodyUnman bodyu = obj as BulletBodyUnman;
706 return BSAPICPP.IsActive2(bodyu.ptr);
707}
708
709public override void SetRestitution(BulletBody obj, float val)
710{
711 BulletBodyUnman bodyu = obj as BulletBodyUnman;
712 BSAPICPP.SetRestitution2(bodyu.ptr, val);
713}
714
715public override float GetRestitution(BulletBody obj)
716{
717 BulletBodyUnman bodyu = obj as BulletBodyUnman;
718 return BSAPICPP.GetRestitution2(bodyu.ptr);
719}
720
721public override void SetFriction(BulletBody obj, float val)
722{
723 BulletBodyUnman bodyu = obj as BulletBodyUnman;
724 BSAPICPP.SetFriction2(bodyu.ptr, val);
725}
726
727public override float GetFriction(BulletBody obj)
728{
729 BulletBodyUnman bodyu = obj as BulletBodyUnman;
730 return BSAPICPP.GetFriction2(bodyu.ptr);
731}
732
733public override Vector3 GetPosition(BulletBody obj)
734{
735 BulletBodyUnman bodyu = obj as BulletBodyUnman;
736 return BSAPICPP.GetPosition2(bodyu.ptr);
737}
738
739public override Quaternion GetOrientation(BulletBody obj)
740{
741 BulletBodyUnman bodyu = obj as BulletBodyUnman;
742 return BSAPICPP.GetOrientation2(bodyu.ptr);
743}
744
745public override void SetTranslation(BulletBody obj, Vector3 position, Quaternion rotation)
746{
747 BulletBodyUnman bodyu = obj as BulletBodyUnman;
748 BSAPICPP.SetTranslation2(bodyu.ptr, position, rotation);
749}
750
751 /*
752public override IntPtr GetBroadphaseHandle(BulletBody obj)
753{
754 BulletBodyUnman bodyu = obj as BulletBodyUnman;
755 return BSAPICPP.GetBroadphaseHandle2(bodyu.ptr);
756}
757
758public override void SetBroadphaseHandle(BulletBody obj, IntPtr handle)
759{
760 BulletBodyUnman bodyu = obj as BulletBodyUnman;
761 BSAPICPP.SetUserPointer2(bodyu.ptr, handle);
762}
763 */
764
765public override void SetInterpolationLinearVelocity(BulletBody obj, Vector3 vel)
766{
767 BulletBodyUnman bodyu = obj as BulletBodyUnman;
768 BSAPICPP.SetInterpolationLinearVelocity2(bodyu.ptr, vel);
769}
770
771public override void SetInterpolationAngularVelocity(BulletBody obj, Vector3 vel)
772{
773 BulletBodyUnman bodyu = obj as BulletBodyUnman;
774 BSAPICPP.SetInterpolationAngularVelocity2(bodyu.ptr, vel);
775}
776
777public override void SetInterpolationVelocity(BulletBody obj, Vector3 linearVel, Vector3 angularVel)
778{
779 BulletBodyUnman bodyu = obj as BulletBodyUnman;
780 BSAPICPP.SetInterpolationVelocity2(bodyu.ptr, linearVel, angularVel);
781}
782
783public override float GetHitFraction(BulletBody obj)
784{
785 BulletBodyUnman bodyu = obj as BulletBodyUnman;
786 return BSAPICPP.GetHitFraction2(bodyu.ptr);
787}
788
789public override void SetHitFraction(BulletBody obj, float val)
790{
791 BulletBodyUnman bodyu = obj as BulletBodyUnman;
792 BSAPICPP.SetHitFraction2(bodyu.ptr, val);
793}
794
795public override CollisionFlags GetCollisionFlags(BulletBody obj)
796{
797 BulletBodyUnman bodyu = obj as BulletBodyUnman;
798 return BSAPICPP.GetCollisionFlags2(bodyu.ptr);
799}
800
801public override CollisionFlags SetCollisionFlags(BulletBody obj, CollisionFlags flags)
802{
803 BulletBodyUnman bodyu = obj as BulletBodyUnman;
804 return BSAPICPP.SetCollisionFlags2(bodyu.ptr, flags);
805}
806
807public override CollisionFlags AddToCollisionFlags(BulletBody obj, CollisionFlags flags)
808{
809 BulletBodyUnman bodyu = obj as BulletBodyUnman;
810 return BSAPICPP.AddToCollisionFlags2(bodyu.ptr, flags);
811}
812
813public override CollisionFlags RemoveFromCollisionFlags(BulletBody obj, CollisionFlags flags)
814{
815 BulletBodyUnman bodyu = obj as BulletBodyUnman;
816 return BSAPICPP.RemoveFromCollisionFlags2(bodyu.ptr, flags);
817}
818
819public override float GetCcdMotionThreshold(BulletBody obj)
820{
821 BulletBodyUnman bodyu = obj as BulletBodyUnman;
822 return BSAPICPP.GetCcdMotionThreshold2(bodyu.ptr);
823}
824
825
826public override void SetCcdMotionThreshold(BulletBody obj, float val)
827{
828 BulletBodyUnman bodyu = obj as BulletBodyUnman;
829 BSAPICPP.SetCcdMotionThreshold2(bodyu.ptr, val);
830}
831
832public override float GetCcdSweptSphereRadius(BulletBody obj)
833{
834 BulletBodyUnman bodyu = obj as BulletBodyUnman;
835 return BSAPICPP.GetCcdSweptSphereRadius2(bodyu.ptr);
836}
837
838public override void SetCcdSweptSphereRadius(BulletBody obj, float val)
839{
840 BulletBodyUnman bodyu = obj as BulletBodyUnman;
841 BSAPICPP.SetCcdSweptSphereRadius2(bodyu.ptr, val);
842}
843
844public override IntPtr GetUserPointer(BulletBody obj)
845{
846 BulletBodyUnman bodyu = obj as BulletBodyUnman;
847 return BSAPICPP.GetUserPointer2(bodyu.ptr);
848}
849
850public override void SetUserPointer(BulletBody obj, IntPtr val)
851{
852 BulletBodyUnman bodyu = obj as BulletBodyUnman;
853 BSAPICPP.SetUserPointer2(bodyu.ptr, val);
854}
855
856// =====================================================================================
857// btRigidBody entries
858public override void ApplyGravity(BulletBody obj)
859{
860 BulletBodyUnman bodyu = obj as BulletBodyUnman;
861 BSAPICPP.ApplyGravity2(bodyu.ptr);
862}
863
864public override void SetGravity(BulletBody obj, Vector3 val)
865{
866 BulletBodyUnman bodyu = obj as BulletBodyUnman;
867 BSAPICPP.SetGravity2(bodyu.ptr, val);
868}
869
870public override Vector3 GetGravity(BulletBody obj)
871{
872 BulletBodyUnman bodyu = obj as BulletBodyUnman;
873 return BSAPICPP.GetGravity2(bodyu.ptr);
874}
875
876public override void SetDamping(BulletBody obj, float lin_damping, float ang_damping)
877{
878 BulletBodyUnman bodyu = obj as BulletBodyUnman;
879 BSAPICPP.SetDamping2(bodyu.ptr, lin_damping, ang_damping);
880}
881
882public override void SetLinearDamping(BulletBody obj, float lin_damping)
883{
884 BulletBodyUnman bodyu = obj as BulletBodyUnman;
885 BSAPICPP.SetLinearDamping2(bodyu.ptr, lin_damping);
886}
887
888public override void SetAngularDamping(BulletBody obj, float ang_damping)
889{
890 BulletBodyUnman bodyu = obj as BulletBodyUnman;
891 BSAPICPP.SetAngularDamping2(bodyu.ptr, ang_damping);
892}
893
894public override float GetLinearDamping(BulletBody obj)
895{
896 BulletBodyUnman bodyu = obj as BulletBodyUnman;
897 return BSAPICPP.GetLinearDamping2(bodyu.ptr);
898}
899
900public override float GetAngularDamping(BulletBody obj)
901{
902 BulletBodyUnman bodyu = obj as BulletBodyUnman;
903 return BSAPICPP.GetAngularDamping2(bodyu.ptr);
904}
905
906public override float GetLinearSleepingThreshold(BulletBody obj)
907{
908 BulletBodyUnman bodyu = obj as BulletBodyUnman;
909 return BSAPICPP.GetLinearSleepingThreshold2(bodyu.ptr);
910}
911
912public override void ApplyDamping(BulletBody obj, float timeStep)
913{
914 BulletBodyUnman bodyu = obj as BulletBodyUnman;
915 BSAPICPP.ApplyDamping2(bodyu.ptr, timeStep);
916}
917
918public override void SetMassProps(BulletBody obj, float mass, Vector3 inertia)
919{
920 BulletBodyUnman bodyu = obj as BulletBodyUnman;
921 BSAPICPP.SetMassProps2(bodyu.ptr, mass, inertia);
922}
923
924public override Vector3 GetLinearFactor(BulletBody obj)
925{
926 BulletBodyUnman bodyu = obj as BulletBodyUnman;
927 return BSAPICPP.GetLinearFactor2(bodyu.ptr);
928}
929
930public override void SetLinearFactor(BulletBody obj, Vector3 factor)
931{
932 BulletBodyUnman bodyu = obj as BulletBodyUnman;
933 BSAPICPP.SetLinearFactor2(bodyu.ptr, factor);
934}
935
936public override void SetCenterOfMassByPosRot(BulletBody obj, Vector3 pos, Quaternion rot)
937{
938 BulletBodyUnman bodyu = obj as BulletBodyUnman;
939 BSAPICPP.SetCenterOfMassByPosRot2(bodyu.ptr, pos, rot);
940}
941
942// Add a force to the object as if its mass is one.
943// Deep down in Bullet: m_totalForce += force*m_linearFactor;
944public override void ApplyCentralForce(BulletBody obj, Vector3 force)
945{
946 BulletBodyUnman bodyu = obj as BulletBodyUnman;
947 BSAPICPP.ApplyCentralForce2(bodyu.ptr, force);
948}
949
950// Set the force being applied to the object as if its mass is one.
951public override void SetObjectForce(BulletBody obj, Vector3 force)
952{
953 BulletBodyUnman bodyu = obj as BulletBodyUnman;
954 BSAPICPP.SetObjectForce2(bodyu.ptr, force);
955}
956
957public override Vector3 GetTotalForce(BulletBody obj)
958{
959 BulletBodyUnman bodyu = obj as BulletBodyUnman;
960 return BSAPICPP.GetTotalForce2(bodyu.ptr);
961}
962
963public override Vector3 GetTotalTorque(BulletBody obj)
964{
965 BulletBodyUnman bodyu = obj as BulletBodyUnman;
966 return BSAPICPP.GetTotalTorque2(bodyu.ptr);
967}
968
969public override Vector3 GetInvInertiaDiagLocal(BulletBody obj)
970{
971 BulletBodyUnman bodyu = obj as BulletBodyUnman;
972 return BSAPICPP.GetInvInertiaDiagLocal2(bodyu.ptr);
973}
974
975public override void SetInvInertiaDiagLocal(BulletBody obj, Vector3 inert)
976{
977 BulletBodyUnman bodyu = obj as BulletBodyUnman;
978 BSAPICPP.SetInvInertiaDiagLocal2(bodyu.ptr, inert);
979}
980
981public override void SetSleepingThresholds(BulletBody obj, float lin_threshold, float ang_threshold)
982{
983 BulletBodyUnman bodyu = obj as BulletBodyUnman;
984 BSAPICPP.SetSleepingThresholds2(bodyu.ptr, lin_threshold, ang_threshold);
985}
986
987// Deep down in Bullet: m_totalTorque += torque*m_angularFactor;
988public override void ApplyTorque(BulletBody obj, Vector3 torque)
989{
990 BulletBodyUnman bodyu = obj as BulletBodyUnman;
991 BSAPICPP.ApplyTorque2(bodyu.ptr, torque);
992}
993
994// Apply force at the given point. Will add torque to the object.
995// Deep down in Bullet: applyCentralForce(force);
996// applyTorque(rel_pos.cross(force*m_linearFactor));
997public override void ApplyForce(BulletBody obj, Vector3 force, Vector3 pos)
998{
999 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1000 BSAPICPP.ApplyForce2(bodyu.ptr, force, pos);
1001}
1002
1003// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
1004// Deep down in Bullet: m_linearVelocity += impulse *m_linearFactor * m_inverseMass;
1005public override void ApplyCentralImpulse(BulletBody obj, Vector3 imp)
1006{
1007 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1008 BSAPICPP.ApplyCentralImpulse2(bodyu.ptr, imp);
1009}
1010
1011// Apply impulse to the object's torque. Force is scaled by object's mass.
1012// Deep down in Bullet: m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
1013public override void ApplyTorqueImpulse(BulletBody obj, Vector3 imp)
1014{
1015 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1016 BSAPICPP.ApplyTorqueImpulse2(bodyu.ptr, imp);
1017}
1018
1019// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
1020// Deep down in Bullet: applyCentralImpulse(impulse);
1021// applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor));
1022public override void ApplyImpulse(BulletBody obj, Vector3 imp, Vector3 pos)
1023{
1024 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1025 BSAPICPP.ApplyImpulse2(bodyu.ptr, imp, pos);
1026}
1027
1028public override void ClearForces(BulletBody obj)
1029{
1030 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1031 BSAPICPP.ClearForces2(bodyu.ptr);
1032}
1033
1034public override void ClearAllForces(BulletBody obj)
1035{
1036 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1037 BSAPICPP.ClearAllForces2(bodyu.ptr);
1038}
1039
1040public override void UpdateInertiaTensor(BulletBody obj)
1041{
1042 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1043 BSAPICPP.UpdateInertiaTensor2(bodyu.ptr);
1044}
1045
1046public override Vector3 GetLinearVelocity(BulletBody obj)
1047{
1048 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1049 return BSAPICPP.GetLinearVelocity2(bodyu.ptr);
1050}
1051
1052public override Vector3 GetAngularVelocity(BulletBody obj)
1053{
1054 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1055 return BSAPICPP.GetAngularVelocity2(bodyu.ptr);
1056}
1057
1058public override void SetLinearVelocity(BulletBody obj, Vector3 vel)
1059{
1060 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1061 BSAPICPP.SetLinearVelocity2(bodyu.ptr, vel);
1062}
1063
1064public override void SetAngularVelocity(BulletBody obj, Vector3 angularVelocity)
1065{
1066 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1067 BSAPICPP.SetAngularVelocity2(bodyu.ptr, angularVelocity);
1068}
1069
1070public override Vector3 GetVelocityInLocalPoint(BulletBody obj, Vector3 pos)
1071{
1072 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1073 return BSAPICPP.GetVelocityInLocalPoint2(bodyu.ptr, pos);
1074}
1075
1076public override void Translate(BulletBody obj, Vector3 trans)
1077{
1078 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1079 BSAPICPP.Translate2(bodyu.ptr, trans);
1080}
1081
1082public override void UpdateDeactivation(BulletBody obj, float timeStep)
1083{
1084 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1085 BSAPICPP.UpdateDeactivation2(bodyu.ptr, timeStep);
1086}
1087
1088public override bool WantsSleeping(BulletBody obj)
1089{
1090 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1091 return BSAPICPP.WantsSleeping2(bodyu.ptr);
1092}
1093
1094public override void SetAngularFactor(BulletBody obj, float factor)
1095{
1096 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1097 BSAPICPP.SetAngularFactor2(bodyu.ptr, factor);
1098}
1099
1100public override void SetAngularFactorV(BulletBody obj, Vector3 factor)
1101{
1102 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1103 BSAPICPP.SetAngularFactorV2(bodyu.ptr, factor);
1104}
1105
1106public override Vector3 GetAngularFactor(BulletBody obj)
1107{
1108 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1109 return BSAPICPP.GetAngularFactor2(bodyu.ptr);
1110}
1111
1112public override bool IsInWorld(BulletWorld world, BulletBody obj)
1113{
1114 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1115 return BSAPICPP.IsInWorld2(bodyu.ptr);
1116}
1117
1118public override void AddConstraintRef(BulletBody obj, BulletConstraint constrain)
1119{
1120 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1121 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
1122 BSAPICPP.AddConstraintRef2(bodyu.ptr, constrainu.ptr);
1123}
1124
1125public override void RemoveConstraintRef(BulletBody obj, BulletConstraint constrain)
1126{
1127 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1128 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
1129 BSAPICPP.RemoveConstraintRef2(bodyu.ptr, constrainu.ptr);
1130}
1131
1132public override BulletConstraint GetConstraintRef(BulletBody obj, int index)
1133{
1134 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1135 return new BulletConstraintUnman(BSAPICPP.GetConstraintRef2(bodyu.ptr, index));
1136}
1137
1138public override int GetNumConstraintRefs(BulletBody obj)
1139{
1140 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1141 return BSAPICPP.GetNumConstraintRefs2(bodyu.ptr);
1142}
1143
1144public override bool SetCollisionGroupMask(BulletBody body, uint filter, uint mask)
1145{
1146 BulletBodyUnman bodyu = body as BulletBodyUnman;
1147 return BSAPICPP.SetCollisionGroupMask2(bodyu.ptr, filter, mask);
1148}
1149
1150// =====================================================================================
1151// btCollisionShape entries
1152
1153public override float GetAngularMotionDisc(BulletShape shape)
1154{
1155 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1156 return BSAPICPP.GetAngularMotionDisc2(shapeu.ptr);
1157}
1158
1159public override float GetContactBreakingThreshold(BulletShape shape, float defaultFactor)
1160{
1161 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1162 return BSAPICPP.GetContactBreakingThreshold2(shapeu.ptr, defaultFactor);
1163}
1164
1165public override bool IsPolyhedral(BulletShape shape)
1166{
1167 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1168 return BSAPICPP.IsPolyhedral2(shapeu.ptr);
1169}
1170
1171public override bool IsConvex2d(BulletShape shape)
1172{
1173 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1174 return BSAPICPP.IsConvex2d2(shapeu.ptr);
1175}
1176
1177public override bool IsConvex(BulletShape shape)
1178{
1179 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1180 return BSAPICPP.IsConvex2(shapeu.ptr);
1181}
1182
1183public override bool IsNonMoving(BulletShape shape)
1184{
1185 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1186 return BSAPICPP.IsNonMoving2(shapeu.ptr);
1187}
1188
1189public override bool IsConcave(BulletShape shape)
1190{
1191 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1192 return BSAPICPP.IsConcave2(shapeu.ptr);
1193}
1194
1195public override bool IsCompound(BulletShape shape)
1196{
1197 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1198 return BSAPICPP.IsCompound2(shapeu.ptr);
1199}
1200
1201public override bool IsSoftBody(BulletShape shape)
1202{
1203 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1204 return BSAPICPP.IsSoftBody2(shapeu.ptr);
1205}
1206
1207public override bool IsInfinite(BulletShape shape)
1208{
1209 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1210 return BSAPICPP.IsInfinite2(shapeu.ptr);
1211}
1212
1213public override void SetLocalScaling(BulletShape shape, Vector3 scale)
1214{
1215 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1216 BSAPICPP.SetLocalScaling2(shapeu.ptr, scale);
1217}
1218
1219public override Vector3 GetLocalScaling(BulletShape shape)
1220{
1221 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1222 return BSAPICPP.GetLocalScaling2(shapeu.ptr);
1223}
1224
1225public override Vector3 CalculateLocalInertia(BulletShape shape, float mass)
1226{
1227 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1228 return BSAPICPP.CalculateLocalInertia2(shapeu.ptr, mass);
1229}
1230
1231public override int GetShapeType(BulletShape shape)
1232{
1233 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1234 return BSAPICPP.GetShapeType2(shapeu.ptr);
1235}
1236
1237public override void SetMargin(BulletShape shape, float val)
1238{
1239 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1240 BSAPICPP.SetMargin2(shapeu.ptr, val);
1241}
1242
1243public override float GetMargin(BulletShape shape)
1244{
1245 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1246 return BSAPICPP.GetMargin2(shapeu.ptr);
1247}
1248
1249// =====================================================================================
1250// Debugging
1251public override void DumpRigidBody(BulletWorld world, BulletBody collisionObject)
1252{
1253 BulletWorldUnman worldu = world as BulletWorldUnman;
1254 BulletBodyUnman bodyu = collisionObject as BulletBodyUnman;
1255 BSAPICPP.DumpRigidBody2(worldu.ptr, bodyu.ptr);
1256}
1257
1258public override void DumpCollisionShape(BulletWorld world, BulletShape collisionShape)
1259{
1260 BulletWorldUnman worldu = world as BulletWorldUnman;
1261 BulletShapeUnman shapeu = collisionShape as BulletShapeUnman;
1262 BSAPICPP.DumpCollisionShape2(worldu.ptr, shapeu.ptr);
1263}
1264
1265public override void DumpConstraint(BulletWorld world, BulletConstraint constrain)
1266{
1267 BulletWorldUnman worldu = world as BulletWorldUnman;
1268 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
1269 BSAPICPP.DumpConstraint2(worldu.ptr, constrainu.ptr);
1270}
1271
1272public override void DumpActivationInfo(BulletWorld world)
1273{
1274 BulletWorldUnman worldu = world as BulletWorldUnman;
1275 BSAPICPP.DumpActivationInfo2(worldu.ptr);
1276}
1277
1278public override void DumpAllInfo(BulletWorld world)
1279{
1280 BulletWorldUnman worldu = world as BulletWorldUnman;
1281 BSAPICPP.DumpAllInfo2(worldu.ptr);
1282}
1283
1284public override void DumpPhysicsStatistics(BulletWorld world)
1285{
1286 BulletWorldUnman worldu = world as BulletWorldUnman;
1287 BSAPICPP.DumpPhysicsStatistics2(worldu.ptr);
1288}
1289public override void ResetBroadphasePool(BulletWorld world)
1290{
1291 BulletWorldUnman worldu = world as BulletWorldUnman;
1292 BSAPICPP.ResetBroadphasePool(worldu.ptr);
1293}
1294public override void ResetConstraintSolver(BulletWorld world)
1295{
1296 BulletWorldUnman worldu = world as BulletWorldUnman;
1297 BSAPICPP.ResetConstraintSolver(worldu.ptr);
1298}
1299
1300// =====================================================================================
1301// =====================================================================================
1302// =====================================================================================
1303// =====================================================================================
1304// =====================================================================================
1305// The actual interface to the unmanaged code
1306static class BSAPICPP
1307{
1308// ===============================================================================
1309// Link back to the managed code for outputting log messages
1310[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
1311public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
1312
1313// ===============================================================================
1314// Initialization and simulation
1315[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1316public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
1317 int maxCollisions, IntPtr collisionArray,
1318 int maxUpdates, IntPtr updateArray,
1319 DebugLogCallback logRoutine);
1320
1321[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1322public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
1323 out int updatedEntityCount, out int collidersCount);
1324
1325[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1326public static extern void Shutdown2(IntPtr sim);
1327
1328[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1329public static extern bool PushUpdate2(IntPtr obj);
1330
1331[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1332public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
1333
1334// =====================================================================================
1335// Mesh, hull, shape and body creation helper routines
1336[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1337public static extern IntPtr CreateMeshShape2(IntPtr world,
1338 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
1339 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1340
1341[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1342public static extern IntPtr CreateHullShape2(IntPtr world,
1343 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
1344
1345[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1346public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
1347
1348[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1349public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
1350
1351[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1352public static extern bool IsNativeShape2(IntPtr shape);
1353
1354[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1355public static extern void SetShapeCollisionMargin2(IntPtr shape, float margin);
1356
1357[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1358public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
1359
1360[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1361public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree);
1362
1363[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1364public static extern int GetNumberOfCompoundChildren2(IntPtr cShape);
1365
1366[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1367public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
1368
1369[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1370public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
1371
1372[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1373public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
1374
1375[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1376public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
1377
1378[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1379public static extern void UpdateChildTransform2(IntPtr pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb);
1380
1381[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1382public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape);
1383
1384[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1385public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id);
1386
1387[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1388public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
1389
1390[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1391public static extern int GetBodyType2(IntPtr obj);
1392
1393[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1394public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
1395
1396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1397public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot);
1398
1399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1400public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
1401
1402[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1403public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
1404
1405// =====================================================================================
1406// Terrain creation and helper routines
1407[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1408public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
1409
1410[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1411public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight,
1412 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap,
1413 float scaleFactor, float collisionMargin);
1414
1415// =====================================================================================
1416// Constraint creation and helper routines
1417[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1418public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1419 Vector3 frame1loc, Quaternion frame1rot,
1420 Vector3 frame2loc, Quaternion frame2rot,
1421 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
1422
1423[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1424public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1425 Vector3 joinPoint,
1426 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
1427
1428[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1429public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1430 Vector3 pivotinA, Vector3 pivotinB,
1431 Vector3 axisInA, Vector3 axisInB,
1432 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
1433
1434[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1435public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
1436
1437[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1438public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
1439
1440[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1441public static extern bool SetFrames2(IntPtr constrain,
1442 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
1443
1444[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1445public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
1446
1447[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1448public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
1449
1450[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1451public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
1452
1453[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1454public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
1455
1456[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1457public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
1458
1459[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1460public static extern bool CalculateTransforms2(IntPtr constrain);
1461
1462[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1463public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
1464
1465[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1466public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
1467
1468// =====================================================================================
1469// btCollisionWorld entries
1470[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1471public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj);
1472
1473[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1474public static extern void UpdateAabbs2(IntPtr world);
1475
1476[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1477public static extern bool GetForceUpdateAllAabbs2(IntPtr world);
1478
1479[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1480public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force);
1481
1482// =====================================================================================
1483// btDynamicsWorld entries
1484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1485public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
1486
1487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1488public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
1489
1490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1491public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
1492
1493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1494public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain);
1495// =====================================================================================
1496// btCollisionObject entries
1497[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1498public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain);
1499
1500[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1501public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict);
1502
1503[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1504public static extern bool HasAnisotripicFriction2(IntPtr constrain);
1505
1506[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1507public static extern void SetContactProcessingThreshold2(IntPtr obj, float val);
1508
1509[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1510public static extern float GetContactProcessingThreshold2(IntPtr obj);
1511
1512[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1513public static extern bool IsStaticObject2(IntPtr obj);
1514
1515[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1516public static extern bool IsKinematicObject2(IntPtr obj);
1517
1518[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1519public static extern bool IsStaticOrKinematicObject2(IntPtr obj);
1520
1521[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1522public static extern bool HasContactResponse2(IntPtr obj);
1523
1524[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1525public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape);
1526
1527[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1528public static extern IntPtr GetCollisionShape2(IntPtr obj);
1529
1530[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1531public static extern int GetActivationState2(IntPtr obj);
1532
1533[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1534public static extern void SetActivationState2(IntPtr obj, int state);
1535
1536[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1537public static extern void SetDeactivationTime2(IntPtr obj, float dtime);
1538
1539[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1540public static extern float GetDeactivationTime2(IntPtr obj);
1541
1542[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1543public static extern void ForceActivationState2(IntPtr obj, ActivationState state);
1544
1545[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1546public static extern void Activate2(IntPtr obj, bool forceActivation);
1547
1548[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1549public static extern bool IsActive2(IntPtr obj);
1550
1551[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1552public static extern void SetRestitution2(IntPtr obj, float val);
1553
1554[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1555public static extern float GetRestitution2(IntPtr obj);
1556
1557[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1558public static extern void SetFriction2(IntPtr obj, float val);
1559
1560[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1561public static extern float GetFriction2(IntPtr obj);
1562
1563 /* Haven't defined the type 'Transform'
1564[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1565public static extern Transform GetWorldTransform2(IntPtr obj);
1566
1567[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1568public static extern void setWorldTransform2(IntPtr obj, Transform trans);
1569 */
1570
1571[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1572public static extern Vector3 GetPosition2(IntPtr obj);
1573
1574[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1575public static extern Quaternion GetOrientation2(IntPtr obj);
1576
1577[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1578public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
1579
1580[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1581public static extern IntPtr GetBroadphaseHandle2(IntPtr obj);
1582
1583[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1584public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle);
1585
1586 /*
1587[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1588public static extern Transform GetInterpolationWorldTransform2(IntPtr obj);
1589
1590[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1591public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans);
1592 */
1593
1594[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1595public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel);
1596
1597[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1598public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel);
1599
1600[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1601public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel);
1602
1603[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1604public static extern float GetHitFraction2(IntPtr obj);
1605
1606[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1607public static extern void SetHitFraction2(IntPtr obj, float val);
1608
1609[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1610public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
1611
1612[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1613public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
1614
1615[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1616public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
1617
1618[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1619public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
1620
1621[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1622public static extern float GetCcdMotionThreshold2(IntPtr obj);
1623
1624[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1625public static extern void SetCcdMotionThreshold2(IntPtr obj, float val);
1626
1627[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1628public static extern float GetCcdSweptSphereRadius2(IntPtr obj);
1629
1630[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1631public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val);
1632
1633[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1634public static extern IntPtr GetUserPointer2(IntPtr obj);
1635
1636[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1637public static extern void SetUserPointer2(IntPtr obj, IntPtr val);
1638
1639// =====================================================================================
1640// btRigidBody entries
1641[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1642public static extern void ApplyGravity2(IntPtr obj);
1643
1644[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1645public static extern void SetGravity2(IntPtr obj, Vector3 val);
1646
1647[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1648public static extern Vector3 GetGravity2(IntPtr obj);
1649
1650[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1651public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
1652
1653[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1654public static extern void SetLinearDamping2(IntPtr obj, float lin_damping);
1655
1656[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1657public static extern void SetAngularDamping2(IntPtr obj, float ang_damping);
1658
1659[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1660public static extern float GetLinearDamping2(IntPtr obj);
1661
1662[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1663public static extern float GetAngularDamping2(IntPtr obj);
1664
1665[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1666public static extern float GetLinearSleepingThreshold2(IntPtr obj);
1667
1668[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1669public static extern float GetAngularSleepingThreshold2(IntPtr obj);
1670
1671[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1672public static extern void ApplyDamping2(IntPtr obj, float timeStep);
1673
1674[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1675public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
1676
1677[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1678public static extern Vector3 GetLinearFactor2(IntPtr obj);
1679
1680[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1681public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor);
1682
1683 /*
1684[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1685public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans);
1686 */
1687
1688[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1689public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot);
1690
1691// Add a force to the object as if its mass is one.
1692[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1693public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force);
1694
1695// Set the force being applied to the object as if its mass is one.
1696[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1697public static extern void SetObjectForce2(IntPtr obj, Vector3 force);
1698
1699[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1700public static extern Vector3 GetTotalForce2(IntPtr obj);
1701
1702[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1703public static extern Vector3 GetTotalTorque2(IntPtr obj);
1704
1705[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1706public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj);
1707
1708[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1709public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert);
1710
1711[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1712public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
1713
1714[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1715public static extern void ApplyTorque2(IntPtr obj, Vector3 torque);
1716
1717// Apply force at the given point. Will add torque to the object.
1718[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1719public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos);
1720
1721// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
1722[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1723public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp);
1724
1725// Apply impulse to the object's torque. Force is scaled by object's mass.
1726[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1727public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp);
1728
1729// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
1730[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1731public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos);
1732
1733[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1734public static extern void ClearForces2(IntPtr obj);
1735
1736[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1737public static extern void ClearAllForces2(IntPtr obj);
1738
1739[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1740public static extern void UpdateInertiaTensor2(IntPtr obj);
1741
1742[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1743public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj);
1744
1745 /*
1746[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1747public static extern Transform GetCenterOfMassTransform2(IntPtr obj);
1748 */
1749
1750[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1751public static extern Vector3 GetLinearVelocity2(IntPtr obj);
1752
1753[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1754public static extern Vector3 GetAngularVelocity2(IntPtr obj);
1755
1756[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1757public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val);
1758
1759[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1760public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
1761
1762[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1763public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos);
1764
1765[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1766public static extern void Translate2(IntPtr obj, Vector3 trans);
1767
1768[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1769public static extern void UpdateDeactivation2(IntPtr obj, float timeStep);
1770
1771[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1772public static extern bool WantsSleeping2(IntPtr obj);
1773
1774[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1775public static extern void SetAngularFactor2(IntPtr obj, float factor);
1776
1777[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1778public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor);
1779
1780[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1781public static extern Vector3 GetAngularFactor2(IntPtr obj);
1782
1783[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1784public static extern bool IsInWorld2(IntPtr obj);
1785
1786[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1787public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain);
1788
1789[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1790public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain);
1791
1792[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1793public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
1794
1795[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1796public static extern int GetNumConstraintRefs2(IntPtr obj);
1797
1798[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1799public static extern bool SetCollisionGroupMask2(IntPtr body, uint filter, uint mask);
1800
1801// =====================================================================================
1802// btCollisionShape entries
1803
1804[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1805public static extern float GetAngularMotionDisc2(IntPtr shape);
1806
1807[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1808public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor);
1809
1810[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1811public static extern bool IsPolyhedral2(IntPtr shape);
1812
1813[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1814public static extern bool IsConvex2d2(IntPtr shape);
1815
1816[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1817public static extern bool IsConvex2(IntPtr shape);
1818
1819[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1820public static extern bool IsNonMoving2(IntPtr shape);
1821
1822[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1823public static extern bool IsConcave2(IntPtr shape);
1824
1825[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1826public static extern bool IsCompound2(IntPtr shape);
1827
1828[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1829public static extern bool IsSoftBody2(IntPtr shape);
1830
1831[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1832public static extern bool IsInfinite2(IntPtr shape);
1833
1834[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1835public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale);
1836
1837[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1838public static extern Vector3 GetLocalScaling2(IntPtr shape);
1839
1840[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1841public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass);
1842
1843[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1844public static extern int GetShapeType2(IntPtr shape);
1845
1846[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1847public static extern void SetMargin2(IntPtr shape, float val);
1848
1849[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1850public static extern float GetMargin2(IntPtr shape);
1851
1852// =====================================================================================
1853// Debugging
1854[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1855public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
1856
1857[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1858public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
1859
1860[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1861public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
1862
1863[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1864public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
1865
1866[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1867public static extern void DumpActivationInfo2(IntPtr sim);
1868
1869[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1870public static extern void DumpAllInfo2(IntPtr sim);
1871
1872[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1873public static extern void DumpPhysicsStatistics2(IntPtr sim);
1874
1875[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1876public static extern void ResetBroadphasePool(IntPtr sim);
1877
1878[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1879public static extern void ResetConstraintSolver(IntPtr sim);
1880
1881}
1882
1883}
1884
1885}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
new file mode 100755
index 0000000..39e62dd
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -0,0 +1,2166 @@
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.IO;
30using System.Runtime.InteropServices;
31using System.Text;
32
33using OpenSim.Framework;
34
35using OpenMetaverse;
36
37using BulletXNA;
38using BulletXNA.LinearMath;
39using BulletXNA.BulletCollision;
40using BulletXNA.BulletDynamics;
41using BulletXNA.BulletCollision.CollisionDispatch;
42
43namespace OpenSim.Region.Physics.BulletSPlugin
44{
45public sealed class BSAPIXNA : BSAPITemplate
46{
47private sealed class BulletWorldXNA : BulletWorld
48{
49 public DiscreteDynamicsWorld world;
50 public BulletWorldXNA(uint id, BSScene physScene, DiscreteDynamicsWorld xx)
51 : base(id, physScene)
52 {
53 world = xx;
54 }
55}
56
57private sealed class BulletBodyXNA : BulletBody
58{
59 public CollisionObject body;
60 public RigidBody rigidBody { get { return RigidBody.Upcast(body); } }
61
62 public BulletBodyXNA(uint id, CollisionObject xx)
63 : base(id)
64 {
65 body = xx;
66 }
67 public override bool HasPhysicalBody
68 {
69 get { return body != null; }
70 }
71 public override void Clear()
72 {
73 body = null;
74 }
75 public override string AddrString
76 {
77 get { return "XNARigidBody"; }
78 }
79}
80
81private sealed class BulletShapeXNA : BulletShape
82{
83 public CollisionShape shape;
84 public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ)
85 : base()
86 {
87 shape = xx;
88 type = typ;
89 }
90 public override bool HasPhysicalShape
91 {
92 get { return shape != null; }
93 }
94 public override void Clear()
95 {
96 shape = null;
97 }
98 public override BulletShape Clone()
99 {
100 return new BulletShapeXNA(shape, type);
101 }
102 public override bool ReferenceSame(BulletShape other)
103 {
104 BulletShapeXNA otheru = other as BulletShapeXNA;
105 return (otheru != null) && (this.shape == otheru.shape);
106
107 }
108 public override string AddrString
109 {
110 get { return "XNACollisionShape"; }
111 }
112}
113private sealed class BulletConstraintXNA : BulletConstraint
114{
115 public TypedConstraint constrain;
116 public BulletConstraintXNA(TypedConstraint xx) : base()
117 {
118 constrain = xx;
119 }
120
121 public override void Clear()
122 {
123 constrain = null;
124 }
125 public override bool HasPhysicalConstraint { get { return constrain != null; } }
126
127 // Used for log messages for a unique display of the memory/object allocated to this instance
128 public override string AddrString
129 {
130 get { return "XNAConstraint"; }
131 }
132}
133 internal int m_maxCollisions;
134 internal CollisionDesc[] UpdatedCollisions;
135 internal int LastCollisionDesc = 0;
136 internal int m_maxUpdatesPerFrame;
137 internal int LastEntityProperty = 0;
138
139 internal EntityProperties[] UpdatedObjects;
140 internal Dictionary<uint, GhostObject> specialCollisionObjects;
141
142 private static int m_collisionsThisFrame;
143 private BSScene PhysicsScene { get; set; }
144
145 public override string BulletEngineName { get { return "BulletXNA"; } }
146 public override string BulletEngineVersion { get; protected set; }
147
148 public BSAPIXNA(string paramName, BSScene physScene)
149 {
150 PhysicsScene = physScene;
151 }
152
153 /// <summary>
154 ///
155 /// </summary>
156 /// <param name="p"></param>
157 /// <param name="p_2"></param>
158 public override bool RemoveObjectFromWorld(BulletWorld pWorld, BulletBody pBody)
159 {
160 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
161 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
162 CollisionObject collisionObject = ((BulletBodyXNA)pBody).body;
163 if (body != null)
164 world.RemoveRigidBody(body);
165 else if (collisionObject != null)
166 world.RemoveCollisionObject(collisionObject);
167 else
168 return false;
169 return true;
170 }
171
172 public override bool AddConstraintToWorld(BulletWorld pWorld, BulletConstraint pConstraint, bool pDisableCollisionsBetweenLinkedObjects)
173 {
174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
175 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain;
176 world.AddConstraint(constraint, pDisableCollisionsBetweenLinkedObjects);
177
178 return true;
179
180 }
181
182 public override bool RemoveConstraintFromWorld(BulletWorld pWorld, BulletConstraint pConstraint)
183 {
184 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
185 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain;
186 world.RemoveConstraint(constraint);
187 return true;
188 }
189
190 public override void SetRestitution(BulletBody pCollisionObject, float pRestitution)
191 {
192 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
193 collisionObject.SetRestitution(pRestitution);
194 }
195
196 public override int GetShapeType(BulletShape pShape)
197 {
198 CollisionShape shape = (pShape as BulletShapeXNA).shape;
199 return (int)shape.GetShapeType();
200 }
201 public override void SetMargin(BulletShape pShape, float pMargin)
202 {
203 CollisionShape shape = (pShape as BulletShapeXNA).shape;
204 shape.SetMargin(pMargin);
205 }
206
207 public override float GetMargin(BulletShape pShape)
208 {
209 CollisionShape shape = (pShape as BulletShapeXNA).shape;
210 return shape.GetMargin();
211 }
212
213 public override void SetLocalScaling(BulletShape pShape, Vector3 pScale)
214 {
215 CollisionShape shape = (pShape as BulletShapeXNA).shape;
216 IndexedVector3 vec = new IndexedVector3(pScale.X, pScale.Y, pScale.Z);
217 shape.SetLocalScaling(ref vec);
218
219 }
220
221 public override void SetContactProcessingThreshold(BulletBody pCollisionObject, float contactprocessingthreshold)
222 {
223 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
224 collisionObject.SetContactProcessingThreshold(contactprocessingthreshold);
225 }
226
227 public override void SetCcdMotionThreshold(BulletBody pCollisionObject, float pccdMotionThreashold)
228 {
229 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
230 collisionObject.SetCcdMotionThreshold(pccdMotionThreashold);
231 }
232
233 public override void SetCcdSweptSphereRadius(BulletBody pCollisionObject, float pCcdSweptSphereRadius)
234 {
235 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
236 collisionObject.SetCcdSweptSphereRadius(pCcdSweptSphereRadius);
237 }
238
239 public override void SetAngularFactorV(BulletBody pBody, Vector3 pAngularFactor)
240 {
241 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
242 body.SetAngularFactor(new IndexedVector3(pAngularFactor.X, pAngularFactor.Y, pAngularFactor.Z));
243 }
244
245 public override CollisionFlags AddToCollisionFlags(BulletBody pCollisionObject, CollisionFlags pcollisionFlags)
246 {
247 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
248 CollisionFlags existingcollisionFlags = (CollisionFlags)(uint)collisionObject.GetCollisionFlags();
249 existingcollisionFlags |= pcollisionFlags;
250 collisionObject.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags)(uint)existingcollisionFlags);
251 return (CollisionFlags) (uint) existingcollisionFlags;
252 }
253
254 public override bool AddObjectToWorld(BulletWorld pWorld, BulletBody pBody)
255 {
256 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
257 CollisionObject cbody = (pBody as BulletBodyXNA).body;
258 RigidBody rbody = cbody as RigidBody;
259
260 // Bullet resets several variables when an object is added to the world. In particular,
261 // BulletXNA resets position and rotation. Gravity is also reset depending on the static/dynamic
262 // type. Of course, the collision flags in the broadphase proxy are initialized to default.
263 IndexedMatrix origPos = cbody.GetWorldTransform();
264 if (rbody != null)
265 {
266 IndexedVector3 origGrav = rbody.GetGravity();
267 world.AddRigidBody(rbody);
268 rbody.SetGravity(origGrav);
269 }
270 else
271 {
272 world.AddCollisionObject(cbody);
273 }
274 cbody.SetWorldTransform(origPos);
275
276 pBody.ApplyCollisionMask(pWorld.physicsScene);
277
278 //if (body.GetBroadphaseHandle() != null)
279 // world.UpdateSingleAabb(body);
280 return true;
281 }
282
283 public override void ForceActivationState(BulletBody pCollisionObject, ActivationState pActivationState)
284 {
285 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
286 collisionObject.ForceActivationState((BulletXNA.BulletCollision.ActivationState)(uint)pActivationState);
287 }
288
289 public override void UpdateSingleAabb(BulletWorld pWorld, BulletBody pCollisionObject)
290 {
291 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
292 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
293 world.UpdateSingleAabb(collisionObject);
294 }
295
296 public override void UpdateAabbs(BulletWorld pWorld) {
297 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
298 world.UpdateAabbs();
299 }
300 public override bool GetForceUpdateAllAabbs(BulletWorld pWorld) {
301 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
302 return world.GetForceUpdateAllAabbs();
303
304 }
305 public override void SetForceUpdateAllAabbs(BulletWorld pWorld, bool pForce)
306 {
307 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
308 world.SetForceUpdateAllAabbs(pForce);
309 }
310
311 public override bool SetCollisionGroupMask(BulletBody pCollisionObject, uint pGroup, uint pMask)
312 {
313 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
314 collisionObject.GetBroadphaseHandle().m_collisionFilterGroup = (BulletXNA.BulletCollision.CollisionFilterGroups) pGroup;
315 collisionObject.GetBroadphaseHandle().m_collisionFilterGroup = (BulletXNA.BulletCollision.CollisionFilterGroups) pGroup;
316 if ((uint) collisionObject.GetBroadphaseHandle().m_collisionFilterGroup == 0)
317 return false;
318 return true;
319 }
320
321 public override void ClearAllForces(BulletBody pCollisionObject)
322 {
323 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
324 IndexedVector3 zeroVector = new IndexedVector3(0, 0, 0);
325 collisionObject.SetInterpolationLinearVelocity(ref zeroVector);
326 collisionObject.SetInterpolationAngularVelocity(ref zeroVector);
327 IndexedMatrix bodytransform = collisionObject.GetWorldTransform();
328
329 collisionObject.SetInterpolationWorldTransform(ref bodytransform);
330
331 if (collisionObject is RigidBody)
332 {
333 RigidBody rigidbody = collisionObject as RigidBody;
334 rigidbody.SetLinearVelocity(zeroVector);
335 rigidbody.SetAngularVelocity(zeroVector);
336 rigidbody.ClearForces();
337 }
338 }
339
340 public override void SetInterpolationAngularVelocity(BulletBody pCollisionObject, Vector3 pVector3)
341 {
342 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
343 IndexedVector3 vec = new IndexedVector3(pVector3.X, pVector3.Y, pVector3.Z);
344 collisionObject.SetInterpolationAngularVelocity(ref vec);
345 }
346
347 public override void SetAngularVelocity(BulletBody pBody, Vector3 pVector3)
348 {
349 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
350 IndexedVector3 vec = new IndexedVector3(pVector3.X, pVector3.Y, pVector3.Z);
351 body.SetAngularVelocity(ref vec);
352 }
353 public override Vector3 GetTotalForce(BulletBody pBody)
354 {
355 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
356 IndexedVector3 iv3 = body.GetTotalForce();
357 return new Vector3(iv3.X, iv3.Y, iv3.Z);
358 }
359 public override Vector3 GetTotalTorque(BulletBody pBody)
360 {
361 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
362 IndexedVector3 iv3 = body.GetTotalTorque();
363 return new Vector3(iv3.X, iv3.Y, iv3.Z);
364 }
365 public override Vector3 GetInvInertiaDiagLocal(BulletBody pBody)
366 {
367 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
368 IndexedVector3 iv3 = body.GetInvInertiaDiagLocal();
369 return new Vector3(iv3.X, iv3.Y, iv3.Z);
370 }
371 public override void SetInvInertiaDiagLocal(BulletBody pBody, Vector3 inert)
372 {
373 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
374 IndexedVector3 iv3 = new IndexedVector3(inert.X, inert.Y, inert.Z);
375 body.SetInvInertiaDiagLocal(ref iv3);
376 }
377 public override void ApplyForce(BulletBody pBody, Vector3 force, Vector3 pos)
378 {
379 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
380 IndexedVector3 forceiv3 = new IndexedVector3(force.X, force.Y, force.Z);
381 IndexedVector3 posiv3 = new IndexedVector3(pos.X, pos.Y, pos.Z);
382 body.ApplyForce(ref forceiv3, ref posiv3);
383 }
384 public override void ApplyImpulse(BulletBody pBody, Vector3 imp, Vector3 pos)
385 {
386 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
387 IndexedVector3 impiv3 = new IndexedVector3(imp.X, imp.Y, imp.Z);
388 IndexedVector3 posiv3 = new IndexedVector3(pos.X, pos.Y, pos.Z);
389 body.ApplyImpulse(ref impiv3, ref posiv3);
390 }
391
392 public override void ClearForces(BulletBody pBody)
393 {
394 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
395 body.ClearForces();
396 }
397
398 public override void SetTranslation(BulletBody pCollisionObject, Vector3 _position, Quaternion _orientation)
399 {
400 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
401 IndexedVector3 vposition = new IndexedVector3(_position.X, _position.Y, _position.Z);
402 IndexedQuaternion vquaternion = new IndexedQuaternion(_orientation.X, _orientation.Y, _orientation.Z,
403 _orientation.W);
404 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion);
405 mat._origin = vposition;
406 collisionObject.SetWorldTransform(mat);
407
408 }
409
410 public override Vector3 GetPosition(BulletBody pCollisionObject)
411 {
412 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
413 IndexedVector3 pos = collisionObject.GetInterpolationWorldTransform()._origin;
414 return new Vector3(pos.X, pos.Y, pos.Z);
415 }
416
417 public override Vector3 CalculateLocalInertia(BulletShape pShape, float pphysMass)
418 {
419 CollisionShape shape = (pShape as BulletShapeXNA).shape;
420 IndexedVector3 inertia = IndexedVector3.Zero;
421 shape.CalculateLocalInertia(pphysMass, out inertia);
422 return new Vector3(inertia.X, inertia.Y, inertia.Z);
423 }
424
425 public override void SetMassProps(BulletBody pBody, float pphysMass, Vector3 plocalInertia)
426 {
427 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
428 if (body != null) // Can't set mass props on collision object.
429 {
430 IndexedVector3 inertia = new IndexedVector3(plocalInertia.X, plocalInertia.Y, plocalInertia.Z);
431 body.SetMassProps(pphysMass, inertia);
432 }
433 }
434
435
436 public override void SetObjectForce(BulletBody pBody, Vector3 _force)
437 {
438 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
439 IndexedVector3 force = new IndexedVector3(_force.X, _force.Y, _force.Z);
440 body.SetTotalForce(ref force);
441 }
442
443 public override void SetFriction(BulletBody pCollisionObject, float _currentFriction)
444 {
445 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
446 collisionObject.SetFriction(_currentFriction);
447 }
448
449 public override void SetLinearVelocity(BulletBody pBody, Vector3 _velocity)
450 {
451 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
452 IndexedVector3 velocity = new IndexedVector3(_velocity.X, _velocity.Y, _velocity.Z);
453 body.SetLinearVelocity(velocity);
454 }
455
456 public override void Activate(BulletBody pCollisionObject, bool pforceactivation)
457 {
458 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
459 collisionObject.Activate(pforceactivation);
460
461 }
462
463 public override Quaternion GetOrientation(BulletBody pCollisionObject)
464 {
465 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
466 IndexedQuaternion mat = collisionObject.GetInterpolationWorldTransform().GetRotation();
467 return new Quaternion(mat.X, mat.Y, mat.Z, mat.W);
468 }
469
470 public override CollisionFlags RemoveFromCollisionFlags(BulletBody pCollisionObject, CollisionFlags pcollisionFlags)
471 {
472 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
473 CollisionFlags existingcollisionFlags = (CollisionFlags)(uint)collisionObject.GetCollisionFlags();
474 existingcollisionFlags &= ~pcollisionFlags;
475 collisionObject.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags)(uint)existingcollisionFlags);
476 return (CollisionFlags)(uint)existingcollisionFlags;
477 }
478
479 public override float GetCcdMotionThreshold(BulletBody pCollisionObject)
480 {
481 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
482 return collisionObject.GetCcdSquareMotionThreshold();
483 }
484
485 public override float GetCcdSweptSphereRadius(BulletBody pCollisionObject)
486 {
487 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
488 return collisionObject.GetCcdSweptSphereRadius();
489
490 }
491
492 public override IntPtr GetUserPointer(BulletBody pCollisionObject)
493 {
494 CollisionObject shape = (pCollisionObject as BulletBodyXNA).body;
495 return (IntPtr)shape.GetUserPointer();
496 }
497
498 public override void SetUserPointer(BulletBody pCollisionObject, IntPtr val)
499 {
500 CollisionObject shape = (pCollisionObject as BulletBodyXNA).body;
501 shape.SetUserPointer(val);
502 }
503
504 public override void SetGravity(BulletBody pBody, Vector3 pGravity)
505 {
506 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
507 if (body != null) // Can't set collisionobject.set gravity
508 {
509 IndexedVector3 gravity = new IndexedVector3(pGravity.X, pGravity.Y, pGravity.Z);
510 body.SetGravity(gravity);
511 }
512 }
513
514 public override bool DestroyConstraint(BulletWorld pWorld, BulletConstraint pConstraint)
515 {
516 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
517 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain;
518 world.RemoveConstraint(constraint);
519 return true;
520 }
521
522 public override bool SetLinearLimits(BulletConstraint pConstraint, Vector3 low, Vector3 high)
523 {
524 Generic6DofConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofConstraint;
525 IndexedVector3 lowlimit = new IndexedVector3(low.X, low.Y, low.Z);
526 IndexedVector3 highlimit = new IndexedVector3(high.X, high.Y, high.Z);
527 constraint.SetLinearLowerLimit(lowlimit);
528 constraint.SetLinearUpperLimit(highlimit);
529 return true;
530 }
531
532 public override bool SetAngularLimits(BulletConstraint pConstraint, Vector3 low, Vector3 high)
533 {
534 Generic6DofConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofConstraint;
535 IndexedVector3 lowlimit = new IndexedVector3(low.X, low.Y, low.Z);
536 IndexedVector3 highlimit = new IndexedVector3(high.X, high.Y, high.Z);
537 constraint.SetAngularLowerLimit(lowlimit);
538 constraint.SetAngularUpperLimit(highlimit);
539 return true;
540 }
541
542 public override void SetConstraintNumSolverIterations(BulletConstraint pConstraint, float cnt)
543 {
544 Generic6DofConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofConstraint;
545 constraint.SetOverrideNumSolverIterations((int)cnt);
546 }
547
548 public override bool CalculateTransforms(BulletConstraint pConstraint)
549 {
550 Generic6DofConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofConstraint;
551 constraint.CalculateTransforms();
552 return true;
553 }
554
555 public override void SetConstraintEnable(BulletConstraint pConstraint, float p_2)
556 {
557 Generic6DofConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofConstraint;
558 constraint.SetEnabled((p_2 == 0) ? false : true);
559 }
560
561
562 //BulletSimAPI.Create6DofConstraint(m_world.ptr, m_body1.ptr, m_body2.ptr,frame1, frame1rot,frame2, frame2rot,useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
563 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
564
565 {
566 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
567 RigidBody body1 = (pBody1 as BulletBodyXNA).rigidBody;
568 RigidBody body2 = (pBody2 as BulletBodyXNA).rigidBody;
569 IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
570 IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
571 IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
572 frame1._origin = frame1v;
573
574 IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z);
575 IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W);
576 IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot);
577 frame2._origin = frame1v;
578
579 Generic6DofConstraint consttr = new Generic6DofConstraint(body1, body2, ref frame1, ref frame2,
580 puseLinearReferenceFrameA);
581 consttr.CalculateTransforms();
582 world.AddConstraint(consttr,pdisableCollisionsBetweenLinkedBodies);
583
584 return new BulletConstraintXNA(consttr);
585 }
586
587
588 /// <summary>
589 ///
590 /// </summary>
591 /// <param name="pWorld"></param>
592 /// <param name="pBody1"></param>
593 /// <param name="pBody2"></param>
594 /// <param name="pjoinPoint"></param>
595 /// <param name="puseLinearReferenceFrameA"></param>
596 /// <param name="pdisableCollisionsBetweenLinkedBodies"></param>
597 /// <returns></returns>
598 public override BulletConstraint Create6DofConstraintToPoint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 pjoinPoint, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
599 {
600 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
601 RigidBody body1 = (pBody1 as BulletBodyXNA).rigidBody;
602 RigidBody body2 = (pBody2 as BulletBodyXNA).rigidBody;
603 IndexedMatrix frame1 = new IndexedMatrix(IndexedBasisMatrix.Identity, new IndexedVector3(0, 0, 0));
604 IndexedMatrix frame2 = new IndexedMatrix(IndexedBasisMatrix.Identity, new IndexedVector3(0, 0, 0));
605
606 IndexedVector3 joinPoint = new IndexedVector3(pjoinPoint.X, pjoinPoint.Y, pjoinPoint.Z);
607 IndexedMatrix mat = IndexedMatrix.Identity;
608 mat._origin = new IndexedVector3(pjoinPoint.X, pjoinPoint.Y, pjoinPoint.Z);
609 frame1._origin = body1.GetWorldTransform().Inverse()*joinPoint;
610 frame2._origin = body2.GetWorldTransform().Inverse()*joinPoint;
611
612 Generic6DofConstraint consttr = new Generic6DofConstraint(body1, body2, ref frame1, ref frame2, puseLinearReferenceFrameA);
613 consttr.CalculateTransforms();
614 world.AddConstraint(consttr, pdisableCollisionsBetweenLinkedBodies);
615
616 return new BulletConstraintXNA(consttr);
617 }
618 //SetFrames(m_constraint.ptr, frameA, frameArot, frameB, frameBrot);
619 public override bool SetFrames(BulletConstraint pConstraint, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot)
620 {
621 Generic6DofConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofConstraint;
622 IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
623 IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
624 IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
625 frame1._origin = frame1v;
626
627 IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z);
628 IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W);
629 IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot);
630 frame2._origin = frame1v;
631 constraint.SetFrames(ref frame1, ref frame2);
632 return true;
633 }
634
635 public override Vector3 GetLinearVelocity(BulletBody pBody)
636 {
637 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
638 IndexedVector3 iv3 = body.GetLinearVelocity();
639 return new Vector3(iv3.X, iv3.Y, iv3.Z);
640 }
641 public override Vector3 GetAngularVelocity(BulletBody pBody)
642 {
643 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
644 IndexedVector3 iv3 = body.GetAngularVelocity();
645 return new Vector3(iv3.X, iv3.Y, iv3.Z);
646 }
647 public override Vector3 GetVelocityInLocalPoint(BulletBody pBody, Vector3 pos)
648 {
649 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
650 IndexedVector3 posiv3 = new IndexedVector3(pos.X, pos.Y, pos.Z);
651 IndexedVector3 iv3 = body.GetVelocityInLocalPoint(ref posiv3);
652 return new Vector3(iv3.X, iv3.Y, iv3.Z);
653 }
654 public override void Translate(BulletBody pCollisionObject, Vector3 trans)
655 {
656 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
657 collisionObject.Translate(new IndexedVector3(trans.X,trans.Y,trans.Z));
658 }
659 public override void UpdateDeactivation(BulletBody pBody, float timeStep)
660 {
661 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
662 body.UpdateDeactivation(timeStep);
663 }
664
665 public override bool WantsSleeping(BulletBody pBody)
666 {
667 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
668 return body.WantsSleeping();
669 }
670
671 public override void SetAngularFactor(BulletBody pBody, float factor)
672 {
673 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
674 body.SetAngularFactor(factor);
675 }
676
677 public override Vector3 GetAngularFactor(BulletBody pBody)
678 {
679 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
680 IndexedVector3 iv3 = body.GetAngularFactor();
681 return new Vector3(iv3.X, iv3.Y, iv3.Z);
682 }
683
684 public override bool IsInWorld(BulletWorld pWorld, BulletBody pCollisionObject)
685 {
686 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
687 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
688 return world.IsInWorld(collisionObject);
689 }
690
691 public override void AddConstraintRef(BulletBody pBody, BulletConstraint pConstraint)
692 {
693 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
694 TypedConstraint constrain = (pConstraint as BulletConstraintXNA).constrain;
695 body.AddConstraintRef(constrain);
696 }
697
698 public override void RemoveConstraintRef(BulletBody pBody, BulletConstraint pConstraint)
699 {
700 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
701 TypedConstraint constrain = (pConstraint as BulletConstraintXNA).constrain;
702 body.RemoveConstraintRef(constrain);
703 }
704
705 public override BulletConstraint GetConstraintRef(BulletBody pBody, int index)
706 {
707 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
708 return new BulletConstraintXNA(body.GetConstraintRef(index));
709 }
710
711 public override int GetNumConstraintRefs(BulletBody pBody)
712 {
713 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
714 return body.GetNumConstraintRefs();
715 }
716
717 public override void SetInterpolationLinearVelocity(BulletBody pCollisionObject, Vector3 VehicleVelocity)
718 {
719 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
720 IndexedVector3 velocity = new IndexedVector3(VehicleVelocity.X, VehicleVelocity.Y, VehicleVelocity.Z);
721 collisionObject.SetInterpolationLinearVelocity(ref velocity);
722 }
723
724 public override bool UseFrameOffset(BulletConstraint pConstraint, float onOff)
725 {
726 Generic6DofConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofConstraint;
727 constraint.SetUseFrameOffset((onOff == 0) ? false : true);
728 return true;
729 }
730 //SetBreakingImpulseThreshold(m_constraint.ptr, threshold);
731 public override bool SetBreakingImpulseThreshold(BulletConstraint pConstraint, float threshold)
732 {
733 Generic6DofConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofConstraint;
734 constraint.SetBreakingImpulseThreshold(threshold);
735 return true;
736 }
737 //BulletSimAPI.SetAngularDamping(Prim.PhysBody.ptr, angularDamping);
738 public override void SetAngularDamping(BulletBody pBody, float angularDamping)
739 {
740 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
741 float lineardamping = body.GetLinearDamping();
742 body.SetDamping(lineardamping, angularDamping);
743
744 }
745
746 public override void UpdateInertiaTensor(BulletBody pBody)
747 {
748 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
749 if (body != null) // can't update inertia tensor on CollisionObject
750 body.UpdateInertiaTensor();
751 }
752
753 public override void RecalculateCompoundShapeLocalAabb(BulletShape pCompoundShape)
754 {
755 CompoundShape shape = (pCompoundShape as BulletShapeXNA).shape as CompoundShape;
756 shape.RecalculateLocalAabb();
757 }
758
759 //BulletSimAPI.GetCollisionFlags(PhysBody.ptr)
760 public override CollisionFlags GetCollisionFlags(BulletBody pCollisionObject)
761 {
762 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
763 uint flags = (uint)collisionObject.GetCollisionFlags();
764 return (CollisionFlags) flags;
765 }
766
767 public override void SetDamping(BulletBody pBody, float pLinear, float pAngular)
768 {
769 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
770 body.SetDamping(pLinear, pAngular);
771 }
772 //PhysBody.ptr, PhysicsScene.Params.deactivationTime);
773 public override void SetDeactivationTime(BulletBody pCollisionObject, float pDeactivationTime)
774 {
775 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
776 collisionObject.SetDeactivationTime(pDeactivationTime);
777 }
778 //SetSleepingThresholds(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
779 public override void SetSleepingThresholds(BulletBody pBody, float plinearSleepingThreshold, float pangularSleepingThreshold)
780 {
781 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
782 body.SetSleepingThresholds(plinearSleepingThreshold, pangularSleepingThreshold);
783 }
784
785 public override CollisionObjectTypes GetBodyType(BulletBody pCollisionObject)
786 {
787 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
788 return (CollisionObjectTypes)(int) collisionObject.GetInternalType();
789 }
790
791 public override void ApplyGravity(BulletBody pBody)
792 {
793
794 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
795 body.ApplyGravity();
796 }
797
798 public override Vector3 GetGravity(BulletBody pBody)
799 {
800 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
801 IndexedVector3 gravity = body.GetGravity();
802 return new Vector3(gravity.X, gravity.Y, gravity.Z);
803 }
804
805 public override void SetLinearDamping(BulletBody pBody, float lin_damping)
806 {
807 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
808 float angularDamping = body.GetAngularDamping();
809 body.SetDamping(lin_damping, angularDamping);
810 }
811
812 public override float GetLinearDamping(BulletBody pBody)
813 {
814 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
815 return body.GetLinearDamping();
816 }
817
818 public override float GetAngularDamping(BulletBody pBody)
819 {
820 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
821 return body.GetAngularDamping();
822 }
823
824 public override float GetLinearSleepingThreshold(BulletBody pBody)
825 {
826 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
827 return body.GetLinearSleepingThreshold();
828 }
829
830 public override void ApplyDamping(BulletBody pBody, float timeStep)
831 {
832 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
833 body.ApplyDamping(timeStep);
834 }
835
836 public override Vector3 GetLinearFactor(BulletBody pBody)
837 {
838 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
839 IndexedVector3 linearFactor = body.GetLinearFactor();
840 return new Vector3(linearFactor.X, linearFactor.Y, linearFactor.Z);
841 }
842
843 public override void SetLinearFactor(BulletBody pBody, Vector3 factor)
844 {
845 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
846 body.SetLinearFactor(new IndexedVector3(factor.X, factor.Y, factor.Z));
847 }
848
849 public override void SetCenterOfMassByPosRot(BulletBody pBody, Vector3 pos, Quaternion rot)
850 {
851 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
852 IndexedQuaternion quat = new IndexedQuaternion(rot.X, rot.Y, rot.Z,rot.W);
853 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(quat);
854 mat._origin = new IndexedVector3(pos.X, pos.Y, pos.Z);
855 body.SetCenterOfMassTransform( ref mat);
856 /* TODO: double check this */
857 }
858
859 //BulletSimAPI.ApplyCentralForce(PhysBody.ptr, fSum);
860 public override void ApplyCentralForce(BulletBody pBody, Vector3 pfSum)
861 {
862 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
863 IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z);
864 body.ApplyCentralForce(ref fSum);
865 }
866 public override void ApplyCentralImpulse(BulletBody pBody, Vector3 pfSum)
867 {
868 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
869 IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z);
870 body.ApplyCentralImpulse(ref fSum);
871 }
872 public override void ApplyTorque(BulletBody pBody, Vector3 pfSum)
873 {
874 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
875 IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z);
876 body.ApplyTorque(ref fSum);
877 }
878 public override void ApplyTorqueImpulse(BulletBody pBody, Vector3 pfSum)
879 {
880 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
881 IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z);
882 body.ApplyTorqueImpulse(ref fSum);
883 }
884
885 public override void DestroyObject(BulletWorld pWorld, BulletBody pBody)
886 {
887 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
888 CollisionObject co = (pBody as BulletBodyXNA).rigidBody;
889 RigidBody bo = co as RigidBody;
890 if (bo == null)
891 {
892
893 if (world.IsInWorld(co))
894 {
895 world.RemoveCollisionObject(co);
896 }
897 }
898 else
899 {
900
901 if (world.IsInWorld(bo))
902 {
903 world.RemoveRigidBody(bo);
904 }
905 }
906 if (co != null)
907 {
908 if (co.GetUserPointer() != null)
909 {
910 uint localId = (uint) co.GetUserPointer();
911 if (specialCollisionObjects.ContainsKey(localId))
912 {
913 specialCollisionObjects.Remove(localId);
914 }
915 }
916 }
917
918 }
919
920 public override void Shutdown(BulletWorld pWorld)
921 {
922 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
923 world.Cleanup();
924 }
925
926 public override BulletShape DuplicateCollisionShape(BulletWorld pWorld, BulletShape pShape, uint id)
927 {
928 CollisionShape shape1 = (pShape as BulletShapeXNA).shape;
929
930 // TODO: Turn this from a reference copy to a Value Copy.
931 BulletShapeXNA shape2 = new BulletShapeXNA(shape1, BSShapeTypeFromBroadPhaseNativeType(shape1.GetShapeType()));
932
933 return shape2;
934 }
935
936 public override bool DeleteCollisionShape(BulletWorld pWorld, BulletShape pShape)
937 {
938 //TODO:
939 return false;
940 }
941 //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation);
942
943 public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
944 {
945 CollisionWorld world = (pWorld as BulletWorldXNA).world;
946 IndexedMatrix mat =
947 IndexedMatrix.CreateFromQuaternion(new IndexedQuaternion(pRawOrientation.X, pRawOrientation.Y,
948 pRawOrientation.Z, pRawOrientation.W));
949 mat._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z);
950 CollisionShape shape = (pShape as BulletShapeXNA).shape;
951 //UpdateSingleAabb(world, shape);
952 // TODO: Feed Update array into null
953 SimMotionState motionState = new SimMotionState(this, pLocalID, mat, null);
954 RigidBody body = new RigidBody(0,motionState,shape,IndexedVector3.Zero);
955 RigidBodyConstructionInfo constructionInfo = new RigidBodyConstructionInfo(0, motionState, shape, IndexedVector3.Zero)
956 {
957 m_mass = 0
958 };
959 /*
960 m_mass = mass;
961 m_motionState =motionState;
962 m_collisionShape = collisionShape;
963 m_localInertia = localInertia;
964 m_linearDamping = 0f;
965 m_angularDamping = 0f;
966 m_friction = 0.5f;
967 m_restitution = 0f;
968 m_linearSleepingThreshold = 0.8f;
969 m_angularSleepingThreshold = 1f;
970 m_additionalDamping = false;
971 m_additionalDampingFactor = 0.005f;
972 m_additionalLinearDampingThresholdSqr = 0.01f;
973 m_additionalAngularDampingThresholdSqr = 0.01f;
974 m_additionalAngularDampingFactor = 0.01f;
975 m_startWorldTransform = IndexedMatrix.Identity;
976 */
977 body.SetUserPointer(pLocalID);
978
979 return new BulletBodyXNA(pLocalID, body);
980 }
981
982
983 public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
984 {
985
986 IndexedMatrix mat =
987 IndexedMatrix.CreateFromQuaternion(new IndexedQuaternion(pRawOrientation.X, pRawOrientation.Y,
988 pRawOrientation.Z, pRawOrientation.W));
989 mat._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z);
990
991 CollisionShape shape = (pShape as BulletShapeXNA).shape;
992
993 // TODO: Feed Update array into null
994 RigidBody body = new RigidBody(0, new DefaultMotionState( mat, IndexedMatrix.Identity), shape, IndexedVector3.Zero);
995 body.SetWorldTransform(mat);
996 body.SetUserPointer(pLocalID);
997 return new BulletBodyXNA(pLocalID, body);
998 }
999 //(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
1000 public override CollisionFlags SetCollisionFlags(BulletBody pCollisionObject, CollisionFlags collisionFlags)
1001 {
1002 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1003 collisionObject.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags) (uint) collisionFlags);
1004 return (CollisionFlags)collisionObject.GetCollisionFlags();
1005 }
1006
1007 public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain)
1008 {
1009
1010 /* TODO */
1011 return Vector3.Zero;
1012 }
1013 public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; }
1014 public override bool HasAnisotripicFriction(BulletConstraint pconstrain) { /* TODO */ return false; }
1015 public override float GetContactProcessingThreshold(BulletBody pBody) { /* TODO */ return 0f; }
1016 public override bool IsStaticObject(BulletBody pCollisionObject)
1017 {
1018 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1019 return collisionObject.IsStaticObject();
1020
1021 }
1022 public override bool IsKinematicObject(BulletBody pCollisionObject)
1023 {
1024 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1025 return collisionObject.IsKinematicObject();
1026 }
1027 public override bool IsStaticOrKinematicObject(BulletBody pCollisionObject)
1028 {
1029 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1030 return collisionObject.IsStaticOrKinematicObject();
1031 }
1032 public override bool HasContactResponse(BulletBody pCollisionObject)
1033 {
1034 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1035 return collisionObject.HasContactResponse();
1036 }
1037 public override int GetActivationState(BulletBody pBody) { /* TODO */ return 0; }
1038 public override void SetActivationState(BulletBody pBody, int state) { /* TODO */ }
1039 public override float GetDeactivationTime(BulletBody pBody) { /* TODO */ return 0f; }
1040 public override bool IsActive(BulletBody pBody) { /* TODO */ return false; }
1041 public override float GetRestitution(BulletBody pBody) { /* TODO */ return 0f; }
1042 public override float GetFriction(BulletBody pBody) { /* TODO */ return 0f; }
1043 public override void SetInterpolationVelocity(BulletBody pBody, Vector3 linearVel, Vector3 angularVel) { /* TODO */ }
1044 public override float GetHitFraction(BulletBody pBody) { /* TODO */ return 0f; }
1045
1046 //(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
1047 public override void SetHitFraction(BulletBody pCollisionObject, float pHitFraction)
1048 {
1049 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1050 collisionObject.SetHitFraction(pHitFraction);
1051 }
1052 //BuildCapsuleShape(physicsScene.World.ptr, 1f, 1f, prim.Scale);
1053 public override BulletShape BuildCapsuleShape(BulletWorld pWorld, float pRadius, float pHeight, Vector3 pScale)
1054 {
1055 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1056 IndexedVector3 scale = new IndexedVector3(pScale.X, pScale.Y, pScale.Z);
1057 CapsuleShapeZ capsuleShapeZ = new CapsuleShapeZ(pRadius, pHeight);
1058 capsuleShapeZ.SetMargin(world.WorldSettings.Params.collisionMargin);
1059 capsuleShapeZ.SetLocalScaling(ref scale);
1060
1061 return new BulletShapeXNA(capsuleShapeZ, BSPhysicsShapeType.SHAPE_CAPSULE); ;
1062 }
1063
1064 public override BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
1065 int maxCollisions, ref CollisionDesc[] collisionArray,
1066 int maxUpdates, ref EntityProperties[] updateArray
1067 )
1068 {
1069
1070 UpdatedObjects = updateArray;
1071 UpdatedCollisions = collisionArray;
1072 /* TODO */
1073 ConfigurationParameters[] configparms = new ConfigurationParameters[1];
1074 configparms[0] = parms;
1075 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
1076 m_maxCollisions = maxCollisions;
1077 m_maxUpdatesPerFrame = maxUpdates;
1078 specialCollisionObjects = new Dictionary<uint, GhostObject>();
1079
1080 return new BulletWorldXNA(1, PhysicsScene, BSAPIXNA.Initialize2(worldExtent, configparms, maxCollisions, ref collisionArray, maxUpdates, ref updateArray, null));
1081 }
1082
1083 private static DiscreteDynamicsWorld Initialize2(Vector3 worldExtent,
1084 ConfigurationParameters[] o,
1085 int mMaxCollisionsPerFrame, ref CollisionDesc[] collisionArray,
1086 int mMaxUpdatesPerFrame, ref EntityProperties[] updateArray,
1087 object mDebugLogCallbackHandle)
1088 {
1089 CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData();
1090
1091 p.angularDamping = BSParam.AngularDamping;
1092 p.defaultFriction = o[0].defaultFriction;
1093 p.defaultFriction = o[0].defaultFriction;
1094 p.defaultDensity = o[0].defaultDensity;
1095 p.defaultRestitution = o[0].defaultRestitution;
1096 p.collisionMargin = o[0].collisionMargin;
1097 p.gravity = o[0].gravity;
1098
1099 p.linearDamping = BSParam.LinearDamping;
1100 p.angularDamping = BSParam.AngularDamping;
1101 p.deactivationTime = BSParam.DeactivationTime;
1102 p.linearSleepingThreshold = BSParam.LinearSleepingThreshold;
1103 p.angularSleepingThreshold = BSParam.AngularSleepingThreshold;
1104 p.ccdMotionThreshold = BSParam.CcdMotionThreshold;
1105 p.ccdSweptSphereRadius = BSParam.CcdSweptSphereRadius;
1106 p.contactProcessingThreshold = BSParam.ContactProcessingThreshold;
1107
1108 p.terrainImplementation = BSParam.TerrainImplementation;
1109 p.terrainFriction = BSParam.TerrainFriction;
1110
1111 p.terrainHitFraction = BSParam.TerrainHitFraction;
1112 p.terrainRestitution = BSParam.TerrainRestitution;
1113 p.terrainCollisionMargin = BSParam.TerrainCollisionMargin;
1114
1115 p.avatarFriction = BSParam.AvatarFriction;
1116 p.avatarStandingFriction = BSParam.AvatarStandingFriction;
1117 p.avatarDensity = BSParam.AvatarDensity;
1118 p.avatarRestitution = BSParam.AvatarRestitution;
1119 p.avatarCapsuleWidth = BSParam.AvatarCapsuleWidth;
1120 p.avatarCapsuleDepth = BSParam.AvatarCapsuleDepth;
1121 p.avatarCapsuleHeight = BSParam.AvatarCapsuleHeight;
1122 p.avatarContactProcessingThreshold = BSParam.AvatarContactProcessingThreshold;
1123
1124 p.vehicleAngularDamping = BSParam.VehicleAngularDamping;
1125
1126 p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize;
1127 p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize;
1128 p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation;
1129 p.shouldForceUpdateAllAabbs = o[0].shouldForceUpdateAllAabbs;
1130 p.shouldRandomizeSolverOrder = o[0].shouldRandomizeSolverOrder;
1131 p.shouldSplitSimulationIslands = o[0].shouldSplitSimulationIslands;
1132 p.shouldEnableFrictionCaching = o[0].shouldEnableFrictionCaching;
1133 p.numberOfSolverIterations = o[0].numberOfSolverIterations;
1134
1135 p.linksetImplementation = BSParam.LinksetImplementation;
1136 p.linkConstraintUseFrameOffset = BSParam.LinkConstraintUseFrameOffset;
1137 p.linkConstraintEnableTransMotor = BSParam.LinkConstraintEnableTransMotor;
1138 p.linkConstraintTransMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
1139 p.linkConstraintTransMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
1140 p.linkConstraintERP = BSParam.LinkConstraintERP;
1141 p.linkConstraintCFM = BSParam.LinkConstraintCFM;
1142 p.linkConstraintSolverIterations = BSParam.LinkConstraintSolverIterations;
1143 p.physicsLoggingFrames = o[0].physicsLoggingFrames;
1144 DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo();
1145
1146 DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration();
1147 CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci);
1148
1149
1150 if (p.maxPersistantManifoldPoolSize > 0)
1151 cci.m_persistentManifoldPoolSize = (int)p.maxPersistantManifoldPoolSize;
1152 if (p.shouldDisableContactPoolDynamicAllocation !=0)
1153 m_dispatcher.SetDispatcherFlags(DispatcherFlags.CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION);
1154 //if (p.maxCollisionAlgorithmPoolSize >0 )
1155
1156 DbvtBroadphase m_broadphase = new DbvtBroadphase();
1157 //IndexedVector3 aabbMin = new IndexedVector3(0, 0, 0);
1158 //IndexedVector3 aabbMax = new IndexedVector3(256, 256, 256);
1159
1160 //AxisSweep3Internal m_broadphase2 = new AxisSweep3Internal(ref aabbMin, ref aabbMax, Convert.ToInt32(0xfffe), 0xffff, ushort.MaxValue/2, null, true);
1161 m_broadphase.GetOverlappingPairCache().SetInternalGhostPairCallback(new GhostPairCallback());
1162
1163 SequentialImpulseConstraintSolver m_solver = new SequentialImpulseConstraintSolver();
1164
1165 DiscreteDynamicsWorld world = new DiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, cci);
1166
1167 world.LastCollisionDesc = 0;
1168 world.LastEntityProperty = 0;
1169
1170 world.WorldSettings.Params = p;
1171 world.SetForceUpdateAllAabbs(p.shouldForceUpdateAllAabbs != 0);
1172 world.GetSolverInfo().m_solverMode = SolverMode.SOLVER_USE_WARMSTARTING | SolverMode.SOLVER_SIMD;
1173 if (p.shouldRandomizeSolverOrder != 0)
1174 world.GetSolverInfo().m_solverMode |= SolverMode.SOLVER_RANDMIZE_ORDER;
1175
1176 world.GetSimulationIslandManager().SetSplitIslands(p.shouldSplitSimulationIslands != 0);
1177 //world.GetDispatchInfo().m_enableSatConvex Not implemented in C# port
1178
1179 if (p.shouldEnableFrictionCaching != 0)
1180 world.GetSolverInfo().m_solverMode |= SolverMode.SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;
1181
1182 if (p.numberOfSolverIterations > 0)
1183 world.GetSolverInfo().m_numIterations = (int) p.numberOfSolverIterations;
1184
1185
1186 world.GetSolverInfo().m_damping = world.WorldSettings.Params.linearDamping;
1187 world.GetSolverInfo().m_restitution = world.WorldSettings.Params.defaultRestitution;
1188 world.GetSolverInfo().m_globalCfm = 0.0f;
1189 world.GetSolverInfo().m_tau = 0.6f;
1190 world.GetSolverInfo().m_friction = 0.3f;
1191 world.GetSolverInfo().m_maxErrorReduction = 20f;
1192 world.GetSolverInfo().m_numIterations = 10;
1193 world.GetSolverInfo().m_erp = 0.2f;
1194 world.GetSolverInfo().m_erp2 = 0.1f;
1195 world.GetSolverInfo().m_sor = 1.0f;
1196 world.GetSolverInfo().m_splitImpulse = false;
1197 world.GetSolverInfo().m_splitImpulsePenetrationThreshold = -0.02f;
1198 world.GetSolverInfo().m_linearSlop = 0.0f;
1199 world.GetSolverInfo().m_warmstartingFactor = 0.85f;
1200 world.GetSolverInfo().m_restingContactRestitutionThreshold = 2;
1201 world.SetForceUpdateAllAabbs(true);
1202
1203 //BSParam.TerrainImplementation = 0;
1204 world.SetGravity(new IndexedVector3(0,0,p.gravity));
1205
1206 return world;
1207 }
1208 //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL
1209 public override bool SetConstraintParam(BulletConstraint pConstraint, ConstraintParams paramIndex, float paramvalue, ConstraintParamAxis axis)
1210 {
1211 Generic6DofConstraint constrain = (pConstraint as BulletConstraintXNA).constrain as Generic6DofConstraint;
1212 if (axis == ConstraintParamAxis.AXIS_LINEAR_ALL || axis == ConstraintParamAxis.AXIS_ALL)
1213 {
1214 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 0);
1215 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 1);
1216 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 2);
1217 }
1218 if (axis == ConstraintParamAxis.AXIS_ANGULAR_ALL || axis == ConstraintParamAxis.AXIS_ALL)
1219 {
1220 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 3);
1221 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 4);
1222 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 5);
1223 }
1224 if (axis == ConstraintParamAxis.AXIS_LINEAR_ALL)
1225 {
1226 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, (int)axis);
1227 }
1228 return true;
1229 }
1230
1231 public override bool PushUpdate(BulletBody pCollisionObject)
1232 {
1233 bool ret = false;
1234 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1235 RigidBody rb = collisionObject as RigidBody;
1236 if (rb != null)
1237 {
1238 SimMotionState sms = rb.GetMotionState() as SimMotionState;
1239 if (sms != null)
1240 {
1241 IndexedMatrix wt = IndexedMatrix.Identity;
1242 sms.GetWorldTransform(out wt);
1243 sms.SetWorldTransform(ref wt, true);
1244 ret = true;
1245 }
1246 }
1247 return ret;
1248
1249 }
1250
1251 public override float GetAngularMotionDisc(BulletShape pShape)
1252 {
1253 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1254 return shape.GetAngularMotionDisc();
1255 }
1256 public override float GetContactBreakingThreshold(BulletShape pShape, float defaultFactor)
1257 {
1258 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1259 return shape.GetContactBreakingThreshold(defaultFactor);
1260 }
1261 public override bool IsCompound(BulletShape pShape)
1262 {
1263 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1264 return shape.IsCompound();
1265 }
1266 public override bool IsSoftBody(BulletShape pShape)
1267 {
1268 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1269 return shape.IsSoftBody();
1270 }
1271 public override bool IsPolyhedral(BulletShape pShape)
1272 {
1273 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1274 return shape.IsPolyhedral();
1275 }
1276 public override bool IsConvex2d(BulletShape pShape)
1277 {
1278 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1279 return shape.IsConvex2d();
1280 }
1281 public override bool IsConvex(BulletShape pShape)
1282 {
1283 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1284 return shape.IsConvex();
1285 }
1286 public override bool IsNonMoving(BulletShape pShape)
1287 {
1288 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1289 return shape.IsNonMoving();
1290 }
1291 public override bool IsConcave(BulletShape pShape)
1292 {
1293 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1294 return shape.IsConcave();
1295 }
1296 public override bool IsInfinite(BulletShape pShape)
1297 {
1298 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1299 return shape.IsInfinite();
1300 }
1301 public override bool IsNativeShape(BulletShape pShape)
1302 {
1303 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1304 bool ret;
1305 switch (shape.GetShapeType())
1306 {
1307 case BroadphaseNativeTypes.BOX_SHAPE_PROXYTYPE:
1308 case BroadphaseNativeTypes.CONE_SHAPE_PROXYTYPE:
1309 case BroadphaseNativeTypes.SPHERE_SHAPE_PROXYTYPE:
1310 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
1311 ret = true;
1312 break;
1313 default:
1314 ret = false;
1315 break;
1316 }
1317 return ret;
1318 }
1319
1320 public override void SetShapeCollisionMargin(BulletShape pShape, float pMargin)
1321 {
1322 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1323 shape.SetMargin(pMargin);
1324 }
1325
1326 //sim.ptr, shape.ptr,prim.LocalID, prim.RawPosition, prim.RawOrientation
1327 public override BulletBody CreateGhostFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
1328 {
1329 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1330 IndexedMatrix bodyTransform = new IndexedMatrix();
1331 bodyTransform._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z);
1332 bodyTransform.SetRotation(new IndexedQuaternion(pRawOrientation.X,pRawOrientation.Y,pRawOrientation.Z,pRawOrientation.W));
1333 GhostObject gObj = new PairCachingGhostObject();
1334 gObj.SetWorldTransform(bodyTransform);
1335 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1336 gObj.SetCollisionShape(shape);
1337 gObj.SetUserPointer(pLocalID);
1338
1339 if (specialCollisionObjects.ContainsKey(pLocalID))
1340 specialCollisionObjects[pLocalID] = gObj;
1341 else
1342 specialCollisionObjects.Add(pLocalID, gObj);
1343
1344 // TODO: Add to Special CollisionObjects!
1345 return new BulletBodyXNA(pLocalID, gObj);
1346 }
1347
1348 public override void SetCollisionShape(BulletWorld pWorld, BulletBody pCollisionObject, BulletShape pShape)
1349 {
1350 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1351 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).body;
1352 if (pShape == null)
1353 {
1354 collisionObject.SetCollisionShape(new EmptyShape());
1355 }
1356 else
1357 {
1358 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1359 collisionObject.SetCollisionShape(shape);
1360 }
1361 }
1362 public override BulletShape GetCollisionShape(BulletBody pCollisionObject)
1363 {
1364 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1365 CollisionShape shape = collisionObject.GetCollisionShape();
1366 return new BulletShapeXNA(shape, BSShapeTypeFromBroadPhaseNativeType(shape.GetShapeType()));
1367 }
1368
1369 //(PhysicsScene.World.ptr, nativeShapeData)
1370 public override BulletShape BuildNativeShape(BulletWorld pWorld, ShapeData pShapeData)
1371 {
1372 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1373 CollisionShape shape = null;
1374 switch (pShapeData.Type)
1375 {
1376 case BSPhysicsShapeType.SHAPE_BOX:
1377 shape = new BoxShape(new IndexedVector3(0.5f,0.5f,0.5f));
1378 break;
1379 case BSPhysicsShapeType.SHAPE_CONE:
1380 shape = new ConeShapeZ(0.5f, 1.0f);
1381 break;
1382 case BSPhysicsShapeType.SHAPE_CYLINDER:
1383 shape = new CylinderShapeZ(new IndexedVector3(0.5f, 0.5f, 0.5f));
1384 break;
1385 case BSPhysicsShapeType.SHAPE_SPHERE:
1386 shape = new SphereShape(0.5f);
1387 break;
1388
1389 }
1390 if (shape != null)
1391 {
1392 IndexedVector3 scaling = new IndexedVector3(pShapeData.Scale.X, pShapeData.Scale.Y, pShapeData.Scale.Z);
1393 shape.SetMargin(world.WorldSettings.Params.collisionMargin);
1394 shape.SetLocalScaling(ref scaling);
1395
1396 }
1397 return new BulletShapeXNA(shape, pShapeData.Type);
1398 }
1399 //PhysicsScene.World.ptr, false
1400 public override BulletShape CreateCompoundShape(BulletWorld pWorld, bool enableDynamicAabbTree)
1401 {
1402 return new BulletShapeXNA(new CompoundShape(enableDynamicAabbTree), BSPhysicsShapeType.SHAPE_COMPOUND);
1403 }
1404
1405 public override int GetNumberOfCompoundChildren(BulletShape pCompoundShape)
1406 {
1407 CompoundShape compoundshape = (pCompoundShape as BulletShapeXNA).shape as CompoundShape;
1408 return compoundshape.GetNumChildShapes();
1409 }
1410 //LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot
1411 public override void AddChildShapeToCompoundShape(BulletShape pCShape, BulletShape paddShape, Vector3 displacementPos, Quaternion displacementRot)
1412 {
1413 IndexedMatrix relativeTransform = new IndexedMatrix();
1414 CompoundShape compoundshape = (pCShape as BulletShapeXNA).shape as CompoundShape;
1415 CollisionShape addshape = (paddShape as BulletShapeXNA).shape;
1416
1417 relativeTransform._origin = new IndexedVector3(displacementPos.X, displacementPos.Y, displacementPos.Z);
1418 relativeTransform.SetRotation(new IndexedQuaternion(displacementRot.X,displacementRot.Y,displacementRot.Z,displacementRot.W));
1419 compoundshape.AddChildShape(ref relativeTransform, addshape);
1420
1421 }
1422
1423 public override BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape pCShape, int pii)
1424 {
1425 CompoundShape compoundshape = (pCShape as BulletShapeXNA).shape as CompoundShape;
1426 CollisionShape ret = null;
1427 ret = compoundshape.GetChildShape(pii);
1428 compoundshape.RemoveChildShapeByIndex(pii);
1429 return new BulletShapeXNA(ret, BSShapeTypeFromBroadPhaseNativeType(ret.GetShapeType()));
1430 }
1431
1432 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) {
1433
1434 if (cShape == null)
1435 return null;
1436 CompoundShape compoundShape = (cShape as BulletShapeXNA).shape as CompoundShape;
1437 CollisionShape shape = compoundShape.GetChildShape(indx);
1438 BulletShape retShape = new BulletShapeXNA(shape, BSShapeTypeFromBroadPhaseNativeType(shape.GetShapeType()));
1439
1440
1441 return retShape;
1442 }
1443
1444 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin)
1445 {
1446 switch (pin)
1447 {
1448 case BroadphaseNativeTypes.BOX_SHAPE_PROXYTYPE:
1449 return BSPhysicsShapeType.SHAPE_BOX;
1450 break;
1451 case BroadphaseNativeTypes.TRIANGLE_SHAPE_PROXYTYPE:
1452 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1453 break;
1454
1455 case BroadphaseNativeTypes.TETRAHEDRAL_SHAPE_PROXYTYPE:
1456 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1457 break;
1458 case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE:
1459 return BSPhysicsShapeType.SHAPE_MESH;
1460 break;
1461 case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE:
1462 return BSPhysicsShapeType.SHAPE_HULL;
1463 break;
1464 case BroadphaseNativeTypes.CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
1465 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1466 break;
1467 case BroadphaseNativeTypes.CUSTOM_POLYHEDRAL_SHAPE_TYPE:
1468 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1469 break;
1470 //implicit convex shapes
1471 case BroadphaseNativeTypes.IMPLICIT_CONVEX_SHAPES_START_HERE:
1472 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1473 break;
1474 case BroadphaseNativeTypes.SPHERE_SHAPE_PROXYTYPE:
1475 return BSPhysicsShapeType.SHAPE_SPHERE;
1476 break;
1477 case BroadphaseNativeTypes.MULTI_SPHERE_SHAPE_PROXYTYPE:
1478 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1479 break;
1480 case BroadphaseNativeTypes.CAPSULE_SHAPE_PROXYTYPE:
1481 return BSPhysicsShapeType.SHAPE_CAPSULE;
1482 break;
1483 case BroadphaseNativeTypes.CONE_SHAPE_PROXYTYPE:
1484 return BSPhysicsShapeType.SHAPE_CONE;
1485 break;
1486 case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE:
1487 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1488 break;
1489 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
1490 return BSPhysicsShapeType.SHAPE_CYLINDER;
1491 break;
1492 case BroadphaseNativeTypes.UNIFORM_SCALING_SHAPE_PROXYTYPE:
1493 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1494 break;
1495 case BroadphaseNativeTypes.MINKOWSKI_SUM_SHAPE_PROXYTYPE:
1496 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1497 break;
1498 case BroadphaseNativeTypes.MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE:
1499 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1500 break;
1501 case BroadphaseNativeTypes.BOX_2D_SHAPE_PROXYTYPE:
1502 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1503 break;
1504 case BroadphaseNativeTypes.CONVEX_2D_SHAPE_PROXYTYPE:
1505 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1506 break;
1507 case BroadphaseNativeTypes.CUSTOM_CONVEX_SHAPE_TYPE:
1508 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1509 break;
1510 //concave shape
1511 case BroadphaseNativeTypes.CONCAVE_SHAPES_START_HERE:
1512 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1513 break;
1514 //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
1515 case BroadphaseNativeTypes.TRIANGLE_MESH_SHAPE_PROXYTYPE:
1516 return BSPhysicsShapeType.SHAPE_MESH;
1517 break;
1518 case BroadphaseNativeTypes.SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE:
1519 return BSPhysicsShapeType.SHAPE_MESH;
1520 break;
1521 ///used for demo integration FAST/Swift collision library and Bullet
1522 case BroadphaseNativeTypes.FAST_CONCAVE_MESH_PROXYTYPE:
1523 return BSPhysicsShapeType.SHAPE_MESH;
1524 break;
1525 //terrain
1526 case BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE:
1527 return BSPhysicsShapeType.SHAPE_HEIGHTMAP;
1528 break;
1529 ///Used for GIMPACT Trimesh integration
1530 case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE:
1531 return BSPhysicsShapeType.SHAPE_MESH;
1532 break;
1533 ///Multimaterial mesh
1534 case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE:
1535 return BSPhysicsShapeType.SHAPE_MESH;
1536 break;
1537
1538 case BroadphaseNativeTypes.EMPTY_SHAPE_PROXYTYPE:
1539 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1540 break;
1541 case BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE:
1542 return BSPhysicsShapeType.SHAPE_GROUNDPLANE;
1543 break;
1544 case BroadphaseNativeTypes.CUSTOM_CONCAVE_SHAPE_TYPE:
1545 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1546 break;
1547 case BroadphaseNativeTypes.CONCAVE_SHAPES_END_HERE:
1548 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1549 break;
1550
1551 case BroadphaseNativeTypes.COMPOUND_SHAPE_PROXYTYPE:
1552 return BSPhysicsShapeType.SHAPE_COMPOUND;
1553 break;
1554
1555 case BroadphaseNativeTypes.SOFTBODY_SHAPE_PROXYTYPE:
1556 return BSPhysicsShapeType.SHAPE_MESH;
1557 break;
1558 case BroadphaseNativeTypes.HFFLUID_SHAPE_PROXYTYPE:
1559 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1560 break;
1561 case BroadphaseNativeTypes.HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE:
1562 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1563 break;
1564 case BroadphaseNativeTypes.INVALID_SHAPE_PROXYTYPE:
1565 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1566 break;
1567 }
1568 return BSPhysicsShapeType.SHAPE_UNKNOWN;
1569 }
1570
1571 public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ }
1572 public override void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb) { /* TODO */ }
1573
1574 public override BulletShape CreateGroundPlaneShape(uint pLocalId, float pheight, float pcollisionMargin)
1575 {
1576 StaticPlaneShape m_planeshape = new StaticPlaneShape(new IndexedVector3(0,0,1),(int)pheight );
1577 m_planeshape.SetMargin(pcollisionMargin);
1578 m_planeshape.SetUserPointer(pLocalId);
1579 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE);
1580 }
1581
1582 public override BulletConstraint CreateHingeConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 ppivotInA, Vector3 ppivotInB, Vector3 paxisInA, Vector3 paxisInB, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
1583 {
1584 HingeConstraint constrain = null;
1585 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1586 RigidBody rb1 = (pBody1 as BulletBodyXNA).rigidBody;
1587 RigidBody rb2 = (pBody2 as BulletBodyXNA).rigidBody;
1588 if (rb1 != null && rb2 != null)
1589 {
1590 IndexedVector3 pivotInA = new IndexedVector3(ppivotInA.X, ppivotInA.Y, ppivotInA.Z);
1591 IndexedVector3 pivotInB = new IndexedVector3(ppivotInB.X, ppivotInB.Y, ppivotInB.Z);
1592 IndexedVector3 axisInA = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.Z);
1593 IndexedVector3 axisInB = new IndexedVector3(paxisInB.X, paxisInB.Y, paxisInB.Z);
1594 world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
1595 }
1596 return new BulletConstraintXNA(constrain);
1597 }
1598
1599 public override BulletShape CreateHullShape(BulletWorld pWorld, int pHullCount, float[] pConvHulls)
1600 {
1601 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1602 CompoundShape compoundshape = new CompoundShape(false);
1603
1604 compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin);
1605 int ii = 1;
1606
1607 for (int i = 0; i < pHullCount; i++)
1608 {
1609 int vertexCount = (int) pConvHulls[ii];
1610
1611 IndexedVector3 centroid = new IndexedVector3(pConvHulls[ii + 1], pConvHulls[ii + 2], pConvHulls[ii + 3]);
1612 IndexedMatrix childTrans = IndexedMatrix.Identity;
1613 childTrans._origin = centroid;
1614
1615 List<IndexedVector3> virts = new List<IndexedVector3>();
1616 int ender = ((ii + 4) + (vertexCount*3));
1617 for (int iii = ii + 4; iii < ender; iii+=3)
1618 {
1619
1620 virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2]));
1621 }
1622 ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount);
1623 convexShape.SetMargin(world.WorldSettings.Params.collisionMargin);
1624 compoundshape.AddChildShape(ref childTrans, convexShape);
1625 ii += (vertexCount*3 + 4);
1626 }
1627
1628 return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL);
1629 }
1630
1631 public override BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
1632 {
1633 /* TODO */ return null;
1634
1635 }
1636
1637 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
1638 {
1639 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount);
1640
1641 for (int iter = 0; iter < pVerticesCount; iter++)
1642 {
1643 if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0;
1644 if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0;
1645 }
1646
1647 ObjectArray<int> indicesarr = new ObjectArray<int>(indices);
1648 ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats);
1649 DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount);
1650 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1651 IndexedMesh mesh = new IndexedMesh();
1652 mesh.m_indexType = PHY_ScalarType.PHY_INTEGER;
1653 mesh.m_numTriangles = pIndicesCount/3;
1654 mesh.m_numVertices = pVerticesCount;
1655 mesh.m_triangleIndexBase = indicesarr;
1656 mesh.m_vertexBase = vertices;
1657 mesh.m_vertexStride = 3;
1658 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1659 mesh.m_triangleIndexStride = 3;
1660
1661 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1662 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1663 BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true);
1664 meshShape.SetMargin(world.WorldSettings.Params.collisionMargin);
1665 // world.UpdateSingleAabb(meshShape);
1666 return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH);
1667
1668 }
1669 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount )
1670 {
1671
1672 String fileName = "objTest3.raw";
1673 String completePath = System.IO.Path.Combine(Util.configDir(), fileName);
1674 StreamWriter sw = new StreamWriter(completePath);
1675 IndexedMesh mesh = new IndexedMesh();
1676
1677 mesh.m_indexType = PHY_ScalarType.PHY_INTEGER;
1678 mesh.m_numTriangles = pIndicesCount / 3;
1679 mesh.m_numVertices = pVerticesCount;
1680 mesh.m_triangleIndexBase = indices;
1681 mesh.m_vertexBase = vertices;
1682 mesh.m_vertexStride = 3;
1683 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1684 mesh.m_triangleIndexStride = 3;
1685
1686 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1687 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1688
1689
1690
1691 for (int i = 0; i < pVerticesCount; i++)
1692 {
1693
1694 string s = vertices[indices[i * 3]].ToString("0.0000");
1695 s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000");
1696 s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000");
1697
1698 sw.Write(s + "\n");
1699 }
1700
1701 sw.Close();
1702 }
1703 public static void DumpRaw(int[] indices, float[] vertices, int pIndicesCount, int pVerticesCount)
1704 {
1705
1706 String fileName = "objTest6.raw";
1707 String completePath = System.IO.Path.Combine(Util.configDir(), fileName);
1708 StreamWriter sw = new StreamWriter(completePath);
1709 IndexedMesh mesh = new IndexedMesh();
1710
1711 mesh.m_indexType = PHY_ScalarType.PHY_INTEGER;
1712 mesh.m_numTriangles = pIndicesCount / 3;
1713 mesh.m_numVertices = pVerticesCount;
1714 mesh.m_triangleIndexBase = indices;
1715 mesh.m_vertexBase = vertices;
1716 mesh.m_vertexStride = 3;
1717 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1718 mesh.m_triangleIndexStride = 3;
1719
1720 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1721 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1722
1723
1724 sw.WriteLine("Indices");
1725 sw.WriteLine(string.Format("int[] indices = new int[{0}];",pIndicesCount));
1726 for (int iter = 0; iter < indices.Length; iter++)
1727 {
1728 sw.WriteLine(string.Format("indices[{0}]={1};",iter,indices[iter]));
1729 }
1730 sw.WriteLine("VerticesFloats");
1731 sw.WriteLine(string.Format("float[] vertices = new float[{0}];", pVerticesCount));
1732 for (int iter = 0; iter < vertices.Length; iter++)
1733 {
1734 sw.WriteLine(string.Format("Vertices[{0}]={1};", iter, vertices[iter].ToString("0.0000")));
1735 }
1736
1737 // for (int i = 0; i < pVerticesCount; i++)
1738 // {
1739 //
1740 // string s = vertices[indices[i * 3]].ToString("0.0000");
1741 // s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000");
1742 // s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000");
1743 //
1744 // sw.Write(s + "\n");
1745 //}
1746
1747 sw.Close();
1748 }
1749
1750 public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
1751 float scaleFactor, float collisionMargin)
1752 {
1753 const int upAxis = 2;
1754 HeightfieldTerrainShape terrainShape = new HeightfieldTerrainShape((int)size.X, (int)size.Y,
1755 heightMap, scaleFactor,
1756 minHeight, maxHeight, upAxis,
1757 false);
1758 terrainShape.SetMargin(collisionMargin + 0.5f);
1759 terrainShape.SetUseDiamondSubdivision(true);
1760 terrainShape.SetUserPointer(id);
1761 return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN);
1762 }
1763
1764 public override bool TranslationalLimitMotor(BulletConstraint pConstraint, float ponOff, float targetVelocity, float maxMotorForce)
1765 {
1766 TypedConstraint tconstrain = (pConstraint as BulletConstraintXNA).constrain;
1767 bool onOff = ponOff != 0;
1768 bool ret = false;
1769
1770 switch (tconstrain.GetConstraintType())
1771 {
1772 case TypedConstraintType.D6_CONSTRAINT_TYPE:
1773 Generic6DofConstraint constrain = tconstrain as Generic6DofConstraint;
1774 constrain.GetTranslationalLimitMotor().m_enableMotor[0] = onOff;
1775 constrain.GetTranslationalLimitMotor().m_targetVelocity[0] = targetVelocity;
1776 constrain.GetTranslationalLimitMotor().m_maxMotorForce[0] = maxMotorForce;
1777 ret = true;
1778 break;
1779 }
1780
1781
1782 return ret;
1783
1784 }
1785
1786 public override int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
1787 out int updatedEntityCount, out int collidersCount)
1788 {
1789 /* TODO */
1790 updatedEntityCount = 0;
1791 collidersCount = 0;
1792
1793
1794 int ret = PhysicsStep2(world,timeStep,maxSubSteps,fixedTimeStep,out updatedEntityCount,out world.physicsScene.m_updateArray, out collidersCount, out world.physicsScene.m_collisionArray);
1795
1796 return ret;
1797 }
1798
1799 private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep,
1800 out int updatedEntityCount, out EntityProperties[] updatedEntities,
1801 out int collidersCount, out CollisionDesc[] colliders)
1802 {
1803 int epic = PhysicsStepint(pWorld, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntities,
1804 out collidersCount, out colliders, m_maxCollisions, m_maxUpdatesPerFrame);
1805 return epic;
1806 }
1807
1808 private int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount,
1809 out EntityProperties[] updatedEntities, out int collidersCount, out CollisionDesc[] colliders, int maxCollisions, int maxUpdates)
1810 {
1811 int numSimSteps = 0;
1812 Array.Clear(UpdatedObjects, 0, UpdatedObjects.Length);
1813 Array.Clear(UpdatedCollisions, 0, UpdatedCollisions.Length);
1814 LastEntityProperty=0;
1815
1816
1817
1818
1819
1820
1821 LastCollisionDesc=0;
1822
1823 updatedEntityCount = 0;
1824 collidersCount = 0;
1825
1826
1827 if (pWorld is BulletWorldXNA)
1828 {
1829 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1830
1831 world.LastCollisionDesc = 0;
1832 world.LastEntityProperty = 0;
1833 numSimSteps = world.StepSimulation(timeStep, m_maxSubSteps, m_fixedTimeStep);
1834 int updates = 0;
1835
1836 PersistentManifold contactManifold;
1837 CollisionObject objA;
1838 CollisionObject objB;
1839 ManifoldPoint manifoldPoint;
1840 PairCachingGhostObject pairCachingGhostObject;
1841
1842 m_collisionsThisFrame = 0;
1843 int numManifolds = world.GetDispatcher().GetNumManifolds();
1844 for (int j = 0; j < numManifolds; j++)
1845 {
1846 contactManifold = world.GetDispatcher().GetManifoldByIndexInternal(j);
1847 int numContacts = contactManifold.GetNumContacts();
1848 if (numContacts == 0)
1849 continue;
1850
1851 objA = contactManifold.GetBody0() as CollisionObject;
1852 objB = contactManifold.GetBody1() as CollisionObject;
1853
1854 manifoldPoint = contactManifold.GetContactPoint(0);
1855 //IndexedVector3 contactPoint = manifoldPoint.GetPositionWorldOnB();
1856 // IndexedVector3 contactNormal = -manifoldPoint.m_normalWorldOnB; // make relative to A
1857
1858 RecordCollision(this, objA, objB, manifoldPoint.GetPositionWorldOnB(), -manifoldPoint.m_normalWorldOnB, manifoldPoint.GetDistance());
1859 m_collisionsThisFrame ++;
1860 if (m_collisionsThisFrame >= 9999999)
1861 break;
1862
1863
1864 }
1865
1866 foreach (GhostObject ghostObject in specialCollisionObjects.Values)
1867 {
1868 pairCachingGhostObject = ghostObject as PairCachingGhostObject;
1869 if (pairCachingGhostObject != null)
1870 {
1871 RecordGhostCollisions(pairCachingGhostObject);
1872 }
1873
1874 }
1875
1876
1877 updatedEntityCount = LastEntityProperty;
1878 updatedEntities = UpdatedObjects;
1879
1880 collidersCount = LastCollisionDesc;
1881 colliders = UpdatedCollisions;
1882
1883
1884 }
1885 else
1886 {
1887 //if (updatedEntities is null)
1888 //updatedEntities = new List<BulletXNA.EntityProperties>();
1889 //updatedEntityCount = 0;
1890
1891
1892 //collidersCount = 0;
1893
1894 updatedEntities = new EntityProperties[0];
1895
1896
1897 colliders = new CollisionDesc[0];
1898
1899 }
1900 return numSimSteps;
1901 }
1902 public void RecordGhostCollisions(PairCachingGhostObject obj)
1903 {
1904 IOverlappingPairCache cache = obj.GetOverlappingPairCache();
1905 ObjectArray<BroadphasePair> pairs = cache.GetOverlappingPairArray();
1906
1907 DiscreteDynamicsWorld world = (PhysicsScene.World as BulletWorldXNA).world;
1908 PersistentManifoldArray manifoldArray = new PersistentManifoldArray();
1909 BroadphasePair collisionPair;
1910 PersistentManifold contactManifold;
1911
1912 CollisionObject objA;
1913 CollisionObject objB;
1914
1915 ManifoldPoint pt;
1916
1917 int numPairs = pairs.Count;
1918
1919 for (int i = 0; i < numPairs; i++)
1920 {
1921 manifoldArray.Clear();
1922 if (LastCollisionDesc < UpdatedCollisions.Length)
1923 break;
1924 collisionPair = world.GetPairCache().FindPair(pairs[i].m_pProxy0, pairs[i].m_pProxy1);
1925 if (collisionPair == null)
1926 continue;
1927
1928 collisionPair.m_algorithm.GetAllContactManifolds(manifoldArray);
1929 for (int j = 0; j < manifoldArray.Count; j++)
1930 {
1931 contactManifold = manifoldArray[j];
1932 int numContacts = contactManifold.GetNumContacts();
1933 objA = contactManifold.GetBody0() as CollisionObject;
1934 objB = contactManifold.GetBody1() as CollisionObject;
1935 for (int p = 0; p < numContacts; p++)
1936 {
1937 pt = contactManifold.GetContactPoint(p);
1938 if (pt.GetDistance() < 0.0f)
1939 {
1940 RecordCollision(this, objA, objB, pt.GetPositionWorldOnA(), -pt.m_normalWorldOnB,pt.GetDistance());
1941 break;
1942 }
1943 }
1944 }
1945 }
1946
1947 }
1948 private static void RecordCollision(BSAPIXNA world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm, float penetration)
1949 {
1950
1951 IndexedVector3 contactNormal = norm;
1952 if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 &&
1953 (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0)
1954 {
1955 return;
1956 }
1957 uint idA = (uint)objA.GetUserPointer();
1958 uint idB = (uint)objB.GetUserPointer();
1959 if (idA > idB)
1960 {
1961 uint temp = idA;
1962 idA = idB;
1963 idB = temp;
1964 contactNormal = -contactNormal;
1965 }
1966
1967 //ulong collisionID = ((ulong) idA << 32) | idB;
1968
1969 CollisionDesc cDesc = new CollisionDesc()
1970 {
1971 aID = idA,
1972 bID = idB,
1973 point = new Vector3(contact.X,contact.Y,contact.Z),
1974 normal = new Vector3(contactNormal.X,contactNormal.Y,contactNormal.Z),
1975 penetration = penetration
1976
1977 };
1978 if (world.LastCollisionDesc < world.UpdatedCollisions.Length)
1979 world.UpdatedCollisions[world.LastCollisionDesc++] = (cDesc);
1980 m_collisionsThisFrame++;
1981
1982
1983 }
1984 private static EntityProperties GetDebugProperties(BulletWorld pWorld, BulletBody pCollisionObject)
1985 {
1986 EntityProperties ent = new EntityProperties();
1987 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1988 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1989 IndexedMatrix transform = collisionObject.GetWorldTransform();
1990 IndexedVector3 LinearVelocity = collisionObject.GetInterpolationLinearVelocity();
1991 IndexedVector3 AngularVelocity = collisionObject.GetInterpolationAngularVelocity();
1992 IndexedQuaternion rotation = transform.GetRotation();
1993 ent.Acceleration = Vector3.Zero;
1994 ent.ID = (uint)collisionObject.GetUserPointer();
1995 ent.Position = new Vector3(transform._origin.X,transform._origin.Y,transform._origin.Z);
1996 ent.Rotation = new Quaternion(rotation.X,rotation.Y,rotation.Z,rotation.W);
1997 ent.Velocity = new Vector3(LinearVelocity.X, LinearVelocity.Y, LinearVelocity.Z);
1998 ent.RotationalVelocity = new Vector3(AngularVelocity.X, AngularVelocity.Y, AngularVelocity.Z);
1999 return ent;
2000 }
2001
2002 public override bool UpdateParameter(BulletWorld world, uint localID, String parm, float value) { /* TODO */
2003 return false; }
2004
2005 public override Vector3 GetLocalScaling(BulletShape pShape)
2006 {
2007 CollisionShape shape = (pShape as BulletShapeXNA).shape;
2008 IndexedVector3 scale = shape.GetLocalScaling();
2009 return new Vector3(scale.X,scale.Y,scale.Z);
2010 }
2011
2012 public bool RayCastGround(BulletWorld pWorld, Vector3 _RayOrigin, float pRayHeight, BulletBody NotMe)
2013 {
2014 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
2015 if (world != null)
2016 {
2017 if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody)
2018 {
2019 CollisionObject AvoidBody = (NotMe as BulletBodyXNA).body;
2020
2021 IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z);
2022 IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight);
2023 using (
2024 ClosestNotMeRayResultCallback rayCallback =
2025 new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody)
2026 )
2027 {
2028 world.RayTest(ref rOrigin, ref rEnd, rayCallback);
2029 if (rayCallback.HasHit())
2030 {
2031 IndexedVector3 hitLocation = rayCallback.m_hitPointWorld;
2032 }
2033 return rayCallback.HasHit();
2034 }
2035 }
2036 }
2037 return false;
2038 }
2039}
2040
2041
2042
2043
2044 public class SimMotionState : DefaultMotionState
2045 {
2046 public RigidBody Rigidbody;
2047 public Vector3 ZeroVect;
2048
2049 private IndexedMatrix m_xform;
2050
2051 private EntityProperties m_properties;
2052 private EntityProperties m_lastProperties;
2053 private BSAPIXNA m_world;
2054
2055 const float POSITION_TOLERANCE = 0.05f;
2056 const float VELOCITY_TOLERANCE = 0.001f;
2057 const float ROTATION_TOLERANCE = 0.01f;
2058 const float ANGULARVELOCITY_TOLERANCE = 0.01f;
2059
2060 public SimMotionState(BSAPIXNA pWorld, uint id, IndexedMatrix starTransform, object frameUpdates)
2061 {
2062 IndexedQuaternion OrientationQuaterion = starTransform.GetRotation();
2063 m_properties = new EntityProperties()
2064 {
2065 ID = id,
2066 Position = new Vector3(starTransform._origin.X, starTransform._origin.Y,starTransform._origin.Z),
2067 Rotation = new Quaternion(OrientationQuaterion.X,OrientationQuaterion.Y,OrientationQuaterion.Z,OrientationQuaterion.W)
2068 };
2069 m_lastProperties = new EntityProperties()
2070 {
2071 ID = id,
2072 Position = new Vector3(starTransform._origin.X, starTransform._origin.Y, starTransform._origin.Z),
2073 Rotation = new Quaternion(OrientationQuaterion.X, OrientationQuaterion.Y, OrientationQuaterion.Z, OrientationQuaterion.W)
2074 };
2075 m_world = pWorld;
2076 m_xform = starTransform;
2077 }
2078
2079 public override void GetWorldTransform(out IndexedMatrix worldTrans)
2080 {
2081 worldTrans = m_xform;
2082 }
2083
2084 public override void SetWorldTransform(IndexedMatrix worldTrans)
2085 {
2086 SetWorldTransform(ref worldTrans);
2087 }
2088
2089 public override void SetWorldTransform(ref IndexedMatrix worldTrans)
2090 {
2091 SetWorldTransform(ref worldTrans, false);
2092 }
2093 public void SetWorldTransform(ref IndexedMatrix worldTrans, bool force)
2094 {
2095 m_xform = worldTrans;
2096 // Put the new transform into m_properties
2097 IndexedQuaternion OrientationQuaternion = m_xform.GetRotation();
2098 IndexedVector3 LinearVelocityVector = Rigidbody.GetLinearVelocity();
2099 IndexedVector3 AngularVelocityVector = Rigidbody.GetAngularVelocity();
2100 m_properties.Position = new Vector3(m_xform._origin.X, m_xform._origin.Y, m_xform._origin.Z);
2101 m_properties.Rotation = new Quaternion(OrientationQuaternion.X, OrientationQuaternion.Y,
2102 OrientationQuaternion.Z, OrientationQuaternion.W);
2103 // A problem with stock Bullet is that we don't get an event when an object is deactivated.
2104 // This means that the last non-zero values for linear and angular velocity
2105 // are left in the viewer who does dead reconning and the objects look like
2106 // they float off.
2107 // BulletSim ships with a patch to Bullet which creates such an event.
2108 m_properties.Velocity = new Vector3(LinearVelocityVector.X, LinearVelocityVector.Y, LinearVelocityVector.Z);
2109 m_properties.RotationalVelocity = new Vector3(AngularVelocityVector.X, AngularVelocityVector.Y, AngularVelocityVector.Z);
2110
2111 if (force
2112
2113 || !AlmostEqual(ref m_lastProperties.Position, ref m_properties.Position, POSITION_TOLERANCE)
2114 || !AlmostEqual(ref m_properties.Rotation, ref m_lastProperties.Rotation, ROTATION_TOLERANCE)
2115 // If the Velocity and AngularVelocity are zero, most likely the object has
2116 // been deactivated. If they both are zero and they have become zero recently,
2117 // make sure a property update is sent so the zeros make it to the viewer.
2118 || ((m_properties.Velocity == ZeroVect && m_properties.RotationalVelocity == ZeroVect)
2119 &&
2120 (m_properties.Velocity != m_lastProperties.Velocity ||
2121 m_properties.RotationalVelocity != m_lastProperties.RotationalVelocity))
2122 // If Velocity and AngularVelocity are non-zero but have changed, send an update.
2123 || !AlmostEqual(ref m_properties.Velocity, ref m_lastProperties.Velocity, VELOCITY_TOLERANCE)
2124 ||
2125 !AlmostEqual(ref m_properties.RotationalVelocity, ref m_lastProperties.RotationalVelocity,
2126 ANGULARVELOCITY_TOLERANCE)
2127 )
2128
2129
2130 {
2131 // Add this update to the list of updates for this frame.
2132 m_lastProperties = m_properties;
2133 if (m_world.LastEntityProperty < m_world.UpdatedObjects.Length)
2134 m_world.UpdatedObjects[m_world.LastEntityProperty++]=(m_properties);
2135
2136 //(*m_updatesThisFrame)[m_properties.ID] = &m_properties;
2137 }
2138
2139
2140
2141
2142 }
2143 public override void SetRigidBody(RigidBody body)
2144 {
2145 Rigidbody = body;
2146 }
2147 internal static bool AlmostEqual(ref Vector3 v1, ref Vector3 v2, float nEpsilon)
2148 {
2149 return
2150 (((v1.X - nEpsilon) < v2.X) && (v2.X < (v1.X + nEpsilon))) &&
2151 (((v1.Y - nEpsilon) < v2.Y) && (v2.Y < (v1.Y + nEpsilon))) &&
2152 (((v1.Z - nEpsilon) < v2.Z) && (v2.Z < (v1.Z + nEpsilon)));
2153 }
2154
2155 internal static bool AlmostEqual(ref Quaternion v1, ref Quaternion v2, float nEpsilon)
2156 {
2157 return
2158 (((v1.X - nEpsilon) < v2.X) && (v2.X < (v1.X + nEpsilon))) &&
2159 (((v1.Y - nEpsilon) < v2.Y) && (v2.Y < (v1.Y + nEpsilon))) &&
2160 (((v1.Z - nEpsilon) < v2.Z) && (v2.Z < (v1.Z + nEpsilon))) &&
2161 (((v1.W - nEpsilon) < v2.W) && (v2.W < (v1.W + nEpsilon)));
2162 }
2163
2164 }
2165}
2166
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
new file mode 100644
index 0000000..5e06c1e
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -0,0 +1,654 @@
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 */
27using System;
28using System.Collections.Generic;
29using System.Runtime.InteropServices;
30using System.Security;
31using System.Text;
32using OpenMetaverse;
33
34namespace OpenSim.Region.Physics.BulletSPlugin {
35
36 // Constraint type values as defined by Bullet
37public enum ConstraintType : int
38{
39 POINT2POINT_CONSTRAINT_TYPE = 3,
40 HINGE_CONSTRAINT_TYPE,
41 CONETWIST_CONSTRAINT_TYPE,
42 D6_CONSTRAINT_TYPE,
43 SLIDER_CONSTRAINT_TYPE,
44 CONTACT_CONSTRAINT_TYPE,
45 D6_SPRING_CONSTRAINT_TYPE,
46 MAX_CONSTRAINT_TYPE
47}
48
49// ===============================================================================
50[StructLayout(LayoutKind.Sequential)]
51public struct ConvexHull
52{
53 Vector3 Offset;
54 int VertexCount;
55 Vector3[] Vertices;
56}
57public enum BSPhysicsShapeType
58{
59 SHAPE_UNKNOWN = 0,
60 SHAPE_CAPSULE = 1,
61 SHAPE_BOX = 2,
62 SHAPE_CONE = 3,
63 SHAPE_CYLINDER = 4,
64 SHAPE_SPHERE = 5,
65 SHAPE_MESH = 6,
66 SHAPE_HULL = 7,
67 // following defined by BulletSim
68 SHAPE_GROUNDPLANE = 20,
69 SHAPE_TERRAIN = 21,
70 SHAPE_COMPOUND = 22,
71 SHAPE_HEIGHTMAP = 23,
72 SHAPE_AVATAR = 24,
73};
74
75// The native shapes have predefined shape hash keys
76public enum FixedShapeKey : ulong
77{
78 KEY_NONE = 0,
79 KEY_BOX = 1,
80 KEY_SPHERE = 2,
81 KEY_CONE = 3,
82 KEY_CYLINDER = 4,
83 KEY_CAPSULE = 5,
84 KEY_AVATAR = 6,
85}
86
87[StructLayout(LayoutKind.Sequential)]
88public struct ShapeData
89{
90 public UInt32 ID;
91 public BSPhysicsShapeType Type;
92 public Vector3 Position;
93 public Quaternion Rotation;
94 public Vector3 Velocity;
95 public Vector3 Scale;
96 public float Mass;
97 public float Buoyancy;
98 public System.UInt64 HullKey;
99 public System.UInt64 MeshKey;
100 public float Friction;
101 public float Restitution;
102 public float Collidable; // true of things bump into this
103 public float Static; // true if a static object. Otherwise gravity, etc.
104 public float Solid; // true if object cannot be passed through
105 public Vector3 Size;
106
107 // note that bools are passed as floats since bool size changes by language and architecture
108 public const float numericTrue = 1f;
109 public const float numericFalse = 0f;
110}
111[StructLayout(LayoutKind.Sequential)]
112public struct SweepHit
113{
114 public UInt32 ID;
115 public float Fraction;
116 public Vector3 Normal;
117 public Vector3 Point;
118}
119[StructLayout(LayoutKind.Sequential)]
120public struct RaycastHit
121{
122 public UInt32 ID;
123 public float Fraction;
124 public Vector3 Normal;
125}
126[StructLayout(LayoutKind.Sequential)]
127public struct CollisionDesc
128{
129 public UInt32 aID;
130 public UInt32 bID;
131 public Vector3 point;
132 public Vector3 normal;
133 public float penetration;
134}
135[StructLayout(LayoutKind.Sequential)]
136public struct EntityProperties
137{
138 public UInt32 ID;
139 public Vector3 Position;
140 public Quaternion Rotation;
141 public Vector3 Velocity;
142 public Vector3 Acceleration;
143 public Vector3 RotationalVelocity;
144
145 public override string ToString()
146 {
147 StringBuilder buff = new StringBuilder();
148 buff.Append("<i=");
149 buff.Append(ID.ToString());
150 buff.Append(",p=");
151 buff.Append(Position.ToString());
152 buff.Append(",r=");
153 buff.Append(Rotation.ToString());
154 buff.Append(",v=");
155 buff.Append(Velocity.ToString());
156 buff.Append(",a=");
157 buff.Append(Acceleration.ToString());
158 buff.Append(",rv=");
159 buff.Append(RotationalVelocity.ToString());
160 buff.Append(">");
161 return buff.ToString();
162 }
163}
164
165// Format of this structure must match the definition in the C++ code
166// NOTE: adding the X causes compile breaks if used. These are unused symbols
167// that can be removed from both here and the unmanaged definition of this structure.
168[StructLayout(LayoutKind.Sequential)]
169public struct ConfigurationParameters
170{
171 public float defaultFriction;
172 public float defaultDensity;
173 public float defaultRestitution;
174 public float collisionMargin;
175 public float gravity;
176
177 public float maxPersistantManifoldPoolSize;
178 public float maxCollisionAlgorithmPoolSize;
179 public float shouldDisableContactPoolDynamicAllocation;
180 public float shouldForceUpdateAllAabbs;
181 public float shouldRandomizeSolverOrder;
182 public float shouldSplitSimulationIslands;
183 public float shouldEnableFrictionCaching;
184 public float numberOfSolverIterations;
185 public float useSingleSidedMeshes;
186
187 public float physicsLoggingFrames;
188
189 public const float numericTrue = 1f;
190 public const float numericFalse = 0f;
191}
192
193
194// The states a bullet collision object can have
195public enum ActivationState : uint
196{
197 ACTIVE_TAG = 1,
198 ISLAND_SLEEPING,
199 WANTS_DEACTIVATION,
200 DISABLE_DEACTIVATION,
201 DISABLE_SIMULATION,
202}
203
204public enum CollisionObjectTypes : int
205{
206 CO_COLLISION_OBJECT = 1 << 0,
207 CO_RIGID_BODY = 1 << 1,
208 CO_GHOST_OBJECT = 1 << 2,
209 CO_SOFT_BODY = 1 << 3,
210 CO_HF_FLUID = 1 << 4,
211 CO_USER_TYPE = 1 << 5,
212}
213
214// Values used by Bullet and BulletSim to control object properties.
215// Bullet's "CollisionFlags" has more to do with operations on the
216// object (if collisions happen, if gravity effects it, ...).
217public enum CollisionFlags : uint
218{
219 CF_STATIC_OBJECT = 1 << 0,
220 CF_KINEMATIC_OBJECT = 1 << 1,
221 CF_NO_CONTACT_RESPONSE = 1 << 2,
222 CF_CUSTOM_MATERIAL_CALLBACK = 1 << 3,
223 CF_CHARACTER_OBJECT = 1 << 4,
224 CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
225 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
226 // Following used by BulletSim to control collisions and updates
227 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
228 BS_FLOATS_ON_WATER = 1 << 11,
229 BS_VEHICLE_COLLISIONS = 1 << 12,
230 BS_NONE = 0,
231 BS_ALL = 0xFFFFFFFF
232};
233
234// Values f collisions groups and masks
235public enum CollisionFilterGroups : uint
236{
237 // Don't use the bit definitions!! Define the use in a
238 // filter/mask definition below. This way collision interactions
239 // are more easily found and debugged.
240 BNoneGroup = 0,
241 BDefaultGroup = 1 << 0, // 0001
242 BStaticGroup = 1 << 1, // 0002
243 BKinematicGroup = 1 << 2, // 0004
244 BDebrisGroup = 1 << 3, // 0008
245 BSensorTrigger = 1 << 4, // 0010
246 BCharacterGroup = 1 << 5, // 0020
247 BAllGroup = 0x000FFFFF,
248 // Filter groups defined by BulletSim
249 BGroundPlaneGroup = 1 << 10, // 0400
250 BTerrainGroup = 1 << 11, // 0800
251 BRaycastGroup = 1 << 12, // 1000
252 BSolidGroup = 1 << 13, // 2000
253 // BLinksetGroup = xx // a linkset proper is either static or dynamic
254 BLinksetChildGroup = 1 << 14, // 4000
255};
256
257// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
258// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
259public enum ConstraintParams : int
260{
261 BT_CONSTRAINT_ERP = 1, // this one is not used in Bullet as of 20120730
262 BT_CONSTRAINT_STOP_ERP,
263 BT_CONSTRAINT_CFM,
264 BT_CONSTRAINT_STOP_CFM,
265};
266public enum ConstraintParamAxis : int
267{
268 AXIS_LINEAR_X = 0,
269 AXIS_LINEAR_Y,
270 AXIS_LINEAR_Z,
271 AXIS_ANGULAR_X,
272 AXIS_ANGULAR_Y,
273 AXIS_ANGULAR_Z,
274 AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls
275 AXIS_ANGULAR_ALL,
276 AXIS_ALL
277};
278
279public abstract class BSAPITemplate
280{
281// Returns the name of the underlying Bullet engine
282public abstract string BulletEngineName { get; }
283public abstract string BulletEngineVersion { get; protected set;}
284
285// Initialization and simulation
286public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
287 int maxCollisions, ref CollisionDesc[] collisionArray,
288 int maxUpdates, ref EntityProperties[] updateArray
289 );
290
291public abstract int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
292 out int updatedEntityCount, out int collidersCount);
293
294public abstract bool UpdateParameter(BulletWorld world, UInt32 localID, String parm, float value);
295
296public abstract void Shutdown(BulletWorld sim);
297
298public abstract bool PushUpdate(BulletBody obj);
299
300// =====================================================================================
301// Mesh, hull, shape and body creation helper routines
302public abstract BulletShape CreateMeshShape(BulletWorld world,
303 int indicesCount, int[] indices,
304 int verticesCount, float[] vertices );
305
306public abstract BulletShape CreateHullShape(BulletWorld world,
307 int hullCount, float[] hulls);
308
309public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape);
310
311public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData);
312
313public abstract bool IsNativeShape(BulletShape shape);
314
315public abstract void SetShapeCollisionMargin(BulletShape shape, float margin);
316
317public abstract BulletShape BuildCapsuleShape(BulletWorld world, float radius, float height, Vector3 scale);
318
319public abstract BulletShape CreateCompoundShape(BulletWorld sim, bool enableDynamicAabbTree);
320
321public abstract int GetNumberOfCompoundChildren(BulletShape cShape);
322
323public abstract void AddChildShapeToCompoundShape(BulletShape cShape, BulletShape addShape, Vector3 pos, Quaternion rot);
324
325public abstract BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx);
326
327public abstract BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx);
328
329public abstract void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape);
330
331public abstract void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb);
332
333public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape);
334
335public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, UInt32 id);
336
337public abstract bool DeleteCollisionShape(BulletWorld world, BulletShape shape);
338
339public abstract CollisionObjectTypes GetBodyType(BulletBody obj);
340
341public abstract BulletBody CreateBodyFromShape(BulletWorld sim, BulletShape shape, UInt32 id, Vector3 pos, Quaternion rot);
342
343public abstract BulletBody CreateBodyWithDefaultMotionState(BulletShape shape, UInt32 id, Vector3 pos, Quaternion rot);
344
345public abstract BulletBody CreateGhostFromShape(BulletWorld sim, BulletShape shape, UInt32 id, Vector3 pos, Quaternion rot);
346
347public abstract void DestroyObject(BulletWorld sim, BulletBody obj);
348
349// =====================================================================================
350public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin);
351
352public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
353 float scaleFactor, float collisionMargin);
354
355// =====================================================================================
356// Constraint creation and helper routines
357public abstract BulletConstraint Create6DofConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
358 Vector3 frame1loc, Quaternion frame1rot,
359 Vector3 frame2loc, Quaternion frame2rot,
360 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
361
362public abstract BulletConstraint Create6DofConstraintToPoint(BulletWorld world, BulletBody obj1, BulletBody obj2,
363 Vector3 joinPoint,
364 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
365
366public abstract BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
367 Vector3 pivotinA, Vector3 pivotinB,
368 Vector3 axisInA, Vector3 axisInB,
369 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
370
371public abstract void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse);
372
373public abstract void SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations);
374
375public abstract bool SetFrames(BulletConstraint constrain,
376 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
377
378public abstract bool SetLinearLimits(BulletConstraint constrain, Vector3 low, Vector3 hi);
379
380public abstract bool SetAngularLimits(BulletConstraint constrain, Vector3 low, Vector3 hi);
381
382public abstract bool UseFrameOffset(BulletConstraint constrain, float enable);
383
384public abstract bool TranslationalLimitMotor(BulletConstraint constrain, float enable, float targetVel, float maxMotorForce);
385
386public abstract bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold);
387
388public abstract bool CalculateTransforms(BulletConstraint constrain);
389
390public abstract bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
391
392public abstract bool DestroyConstraint(BulletWorld world, BulletConstraint constrain);
393
394// =====================================================================================
395// btCollisionWorld entries
396public abstract void UpdateSingleAabb(BulletWorld world, BulletBody obj);
397
398public abstract void UpdateAabbs(BulletWorld world);
399
400public abstract bool GetForceUpdateAllAabbs(BulletWorld world);
401
402public abstract void SetForceUpdateAllAabbs(BulletWorld world, bool force);
403
404// =====================================================================================
405// btDynamicsWorld entries
406// public abstract bool AddObjectToWorld(BulletWorld world, BulletBody obj, Vector3 pos, Quaternion rot);
407public abstract bool AddObjectToWorld(BulletWorld world, BulletBody obj);
408
409public abstract bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj);
410
411public abstract bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects);
412
413public abstract bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain);
414// =====================================================================================
415// btCollisionObject entries
416public abstract Vector3 GetAnisotripicFriction(BulletConstraint constrain);
417
418public abstract Vector3 SetAnisotripicFriction(BulletConstraint constrain, Vector3 frict);
419
420public abstract bool HasAnisotripicFriction(BulletConstraint constrain);
421
422public abstract void SetContactProcessingThreshold(BulletBody obj, float val);
423
424public abstract float GetContactProcessingThreshold(BulletBody obj);
425
426public abstract bool IsStaticObject(BulletBody obj);
427
428public abstract bool IsKinematicObject(BulletBody obj);
429
430public abstract bool IsStaticOrKinematicObject(BulletBody obj);
431
432public abstract bool HasContactResponse(BulletBody obj);
433
434public abstract void SetCollisionShape(BulletWorld sim, BulletBody obj, BulletShape shape);
435
436public abstract BulletShape GetCollisionShape(BulletBody obj);
437
438public abstract int GetActivationState(BulletBody obj);
439
440public abstract void SetActivationState(BulletBody obj, int state);
441
442public abstract void SetDeactivationTime(BulletBody obj, float dtime);
443
444public abstract float GetDeactivationTime(BulletBody obj);
445
446public abstract void ForceActivationState(BulletBody obj, ActivationState state);
447
448public abstract void Activate(BulletBody obj, bool forceActivation);
449
450public abstract bool IsActive(BulletBody obj);
451
452public abstract void SetRestitution(BulletBody obj, float val);
453
454public abstract float GetRestitution(BulletBody obj);
455
456public abstract void SetFriction(BulletBody obj, float val);
457
458public abstract float GetFriction(BulletBody obj);
459
460public abstract Vector3 GetPosition(BulletBody obj);
461
462public abstract Quaternion GetOrientation(BulletBody obj);
463
464public abstract void SetTranslation(BulletBody obj, Vector3 position, Quaternion rotation);
465
466// public abstract IntPtr GetBroadphaseHandle(BulletBody obj);
467
468// public abstract void SetBroadphaseHandle(BulletBody obj, IntPtr handle);
469
470public abstract void SetInterpolationLinearVelocity(BulletBody obj, Vector3 vel);
471
472public abstract void SetInterpolationAngularVelocity(BulletBody obj, Vector3 vel);
473
474public abstract void SetInterpolationVelocity(BulletBody obj, Vector3 linearVel, Vector3 angularVel);
475
476public abstract float GetHitFraction(BulletBody obj);
477
478public abstract void SetHitFraction(BulletBody obj, float val);
479
480public abstract CollisionFlags GetCollisionFlags(BulletBody obj);
481
482public abstract CollisionFlags SetCollisionFlags(BulletBody obj, CollisionFlags flags);
483
484public abstract CollisionFlags AddToCollisionFlags(BulletBody obj, CollisionFlags flags);
485
486public abstract CollisionFlags RemoveFromCollisionFlags(BulletBody obj, CollisionFlags flags);
487
488public abstract float GetCcdMotionThreshold(BulletBody obj);
489
490public abstract void SetCcdMotionThreshold(BulletBody obj, float val);
491
492public abstract float GetCcdSweptSphereRadius(BulletBody obj);
493
494public abstract void SetCcdSweptSphereRadius(BulletBody obj, float val);
495
496public abstract IntPtr GetUserPointer(BulletBody obj);
497
498public abstract void SetUserPointer(BulletBody obj, IntPtr val);
499
500// =====================================================================================
501// btRigidBody entries
502public abstract void ApplyGravity(BulletBody obj);
503
504public abstract void SetGravity(BulletBody obj, Vector3 val);
505
506public abstract Vector3 GetGravity(BulletBody obj);
507
508public abstract void SetDamping(BulletBody obj, float lin_damping, float ang_damping);
509
510public abstract void SetLinearDamping(BulletBody obj, float lin_damping);
511
512public abstract void SetAngularDamping(BulletBody obj, float ang_damping);
513
514public abstract float GetLinearDamping(BulletBody obj);
515
516public abstract float GetAngularDamping(BulletBody obj);
517
518public abstract float GetLinearSleepingThreshold(BulletBody obj);
519
520public abstract void ApplyDamping(BulletBody obj, float timeStep);
521
522public abstract void SetMassProps(BulletBody obj, float mass, Vector3 inertia);
523
524public abstract Vector3 GetLinearFactor(BulletBody obj);
525
526public abstract void SetLinearFactor(BulletBody obj, Vector3 factor);
527
528public abstract void SetCenterOfMassByPosRot(BulletBody obj, Vector3 pos, Quaternion rot);
529
530// Add a force to the object as if its mass is one.
531public abstract void ApplyCentralForce(BulletBody obj, Vector3 force);
532
533// Set the force being applied to the object as if its mass is one.
534public abstract void SetObjectForce(BulletBody obj, Vector3 force);
535
536public abstract Vector3 GetTotalForce(BulletBody obj);
537
538public abstract Vector3 GetTotalTorque(BulletBody obj);
539
540public abstract Vector3 GetInvInertiaDiagLocal(BulletBody obj);
541
542public abstract void SetInvInertiaDiagLocal(BulletBody obj, Vector3 inert);
543
544public abstract void SetSleepingThresholds(BulletBody obj, float lin_threshold, float ang_threshold);
545
546public abstract void ApplyTorque(BulletBody obj, Vector3 torque);
547
548// Apply force at the given point. Will add torque to the object.
549public abstract void ApplyForce(BulletBody obj, Vector3 force, Vector3 pos);
550
551// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
552public abstract void ApplyCentralImpulse(BulletBody obj, Vector3 imp);
553
554// Apply impulse to the object's torque. Force is scaled by object's mass.
555public abstract void ApplyTorqueImpulse(BulletBody obj, Vector3 imp);
556
557// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
558public abstract void ApplyImpulse(BulletBody obj, Vector3 imp, Vector3 pos);
559
560public abstract void ClearForces(BulletBody obj);
561
562public abstract void ClearAllForces(BulletBody obj);
563
564public abstract void UpdateInertiaTensor(BulletBody obj);
565
566public abstract Vector3 GetLinearVelocity(BulletBody obj);
567
568public abstract Vector3 GetAngularVelocity(BulletBody obj);
569
570public abstract void SetLinearVelocity(BulletBody obj, Vector3 val);
571
572public abstract void SetAngularVelocity(BulletBody obj, Vector3 angularVelocity);
573
574public abstract Vector3 GetVelocityInLocalPoint(BulletBody obj, Vector3 pos);
575
576public abstract void Translate(BulletBody obj, Vector3 trans);
577
578public abstract void UpdateDeactivation(BulletBody obj, float timeStep);
579
580public abstract bool WantsSleeping(BulletBody obj);
581
582public abstract void SetAngularFactor(BulletBody obj, float factor);
583
584public abstract void SetAngularFactorV(BulletBody obj, Vector3 factor);
585
586public abstract Vector3 GetAngularFactor(BulletBody obj);
587
588public abstract bool IsInWorld(BulletWorld world, BulletBody obj);
589
590public abstract void AddConstraintRef(BulletBody obj, BulletConstraint constrain);
591
592public abstract void RemoveConstraintRef(BulletBody obj, BulletConstraint constrain);
593
594public abstract BulletConstraint GetConstraintRef(BulletBody obj, int index);
595
596public abstract int GetNumConstraintRefs(BulletBody obj);
597
598public abstract bool SetCollisionGroupMask(BulletBody body, UInt32 filter, UInt32 mask);
599
600// =====================================================================================
601// btCollisionShape entries
602
603public abstract float GetAngularMotionDisc(BulletShape shape);
604
605public abstract float GetContactBreakingThreshold(BulletShape shape, float defaultFactor);
606
607public abstract bool IsPolyhedral(BulletShape shape);
608
609public abstract bool IsConvex2d(BulletShape shape);
610
611public abstract bool IsConvex(BulletShape shape);
612
613public abstract bool IsNonMoving(BulletShape shape);
614
615public abstract bool IsConcave(BulletShape shape);
616
617public abstract bool IsCompound(BulletShape shape);
618
619public abstract bool IsSoftBody(BulletShape shape);
620
621public abstract bool IsInfinite(BulletShape shape);
622
623public abstract void SetLocalScaling(BulletShape shape, Vector3 scale);
624
625public abstract Vector3 GetLocalScaling(BulletShape shape);
626
627public abstract Vector3 CalculateLocalInertia(BulletShape shape, float mass);
628
629public abstract int GetShapeType(BulletShape shape);
630
631public abstract void SetMargin(BulletShape shape, float val);
632
633public abstract float GetMargin(BulletShape shape);
634
635// =====================================================================================
636// Debugging
637public virtual void DumpRigidBody(BulletWorld sim, BulletBody collisionObject) { }
638
639public virtual void DumpCollisionShape(BulletWorld sim, BulletShape collisionShape) { }
640
641public virtual void DumpConstraint(BulletWorld sim, BulletConstraint constrain) { }
642
643public virtual void DumpActivationInfo(BulletWorld sim) { }
644
645public virtual void DumpAllInfo(BulletWorld sim) { }
646
647public virtual void DumpPhysicsStatistics(BulletWorld sim) { }
648
649public virtual void ResetBroadphasePool(BulletWorld sim) { }
650
651public virtual void ResetConstraintSolver(BulletWorld sim) { }
652
653};
654}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 4c195e1..192bcb5 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -58,17 +58,16 @@ public sealed class BSCharacter : BSPhysObject
58 private bool _flying; 58 private bool _flying;
59 private bool _setAlwaysRun; 59 private bool _setAlwaysRun;
60 private bool _throttleUpdates; 60 private bool _throttleUpdates;
61 private bool _isColliding;
62 private bool _collidingObj;
63 private bool _floatOnWater; 61 private bool _floatOnWater;
64 private OMV.Vector3 _rotationalVelocity; 62 private OMV.Vector3 _rotationalVelocity;
65 private bool _kinematic; 63 private bool _kinematic;
66 private float _buoyancy; 64 private float _buoyancy;
67 65
68 // The friction and velocity of the avatar is modified depending on whether walking or not. 66 // The friction and velocity of the avatar is modified depending on whether walking or not.
69 private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar
70 private float _currentFriction; // the friction currently being used (changed by setVelocity). 67 private float _currentFriction; // the friction currently being used (changed by setVelocity).
71 68
69 private BSVMotor _velocityMotor;
70
72 private OMV.Vector3 _PIDTarget; 71 private OMV.Vector3 _PIDTarget;
73 private bool _usePID; 72 private bool _usePID;
74 private float _PIDTau; 73 private float _PIDTau;
@@ -83,34 +82,36 @@ public sealed class BSCharacter : BSPhysObject
83 _physicsActorType = (int)ActorTypes.Agent; 82 _physicsActorType = (int)ActorTypes.Agent;
84 _position = pos; 83 _position = pos;
85 84
86 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
87 // replace with the default values.
88 _size = size;
89 if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth;
90 if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth;
91
92 _flying = isFlying; 85 _flying = isFlying;
93 _orientation = OMV.Quaternion.Identity; 86 _orientation = OMV.Quaternion.Identity;
94 _velocity = OMV.Vector3.Zero; 87 _velocity = OMV.Vector3.Zero;
95 _appliedVelocity = OMV.Vector3.Zero;
96 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 88 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
97 _currentFriction = PhysicsScene.Params.avatarStandingFriction; 89 _currentFriction = BSParam.AvatarStandingFriction;
98 _avatarDensity = PhysicsScene.Params.avatarDensity; 90 _avatarDensity = BSParam.AvatarDensity;
91
92 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
93 // replace with the default values.
94 _size = size;
95 if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth;
96 if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth;
99 97
100 // The dimensions of the avatar capsule are kept in the scale. 98 // The dimensions of the physical capsule are kept in the scale.
101 // Physics creates a unit capsule which is scaled by the physics engine. 99 // Physics creates a unit capsule which is scaled by the physics engine.
102 ComputeAvatarScale(_size); 100 Scale = ComputeAvatarScale(_size);
103 // set _avatarVolume and _mass based on capsule size, _density and Scale 101 // set _avatarVolume and _mass based on capsule size, _density and Scale
104 ComputeAvatarVolumeAndMass(); 102 ComputeAvatarVolumeAndMass();
103
104 SetupMovementMotor();
105
105 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", 106 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
106 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); 107 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
107 108
108 // do actual create at taint time 109 // do actual creation in taint time
109 PhysicsScene.TaintedObject("BSCharacter.create", delegate() 110 PhysicsScene.TaintedObject("BSCharacter.create", delegate()
110 { 111 {
111 DetailLog("{0},BSCharacter.create,taint", LocalID); 112 DetailLog("{0},BSCharacter.create,taint", LocalID);
112 // New body and shape into PhysBody and PhysShape 113 // New body and shape into PhysBody and PhysShape
113 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); 114 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this);
114 115
115 SetPhysicalProperties(); 116 SetPhysicalProperties();
116 }); 117 });
@@ -120,54 +121,201 @@ public sealed class BSCharacter : BSPhysObject
120 // called when this character is being destroyed and the resources should be released 121 // called when this character is being destroyed and the resources should be released
121 public override void Destroy() 122 public override void Destroy()
122 { 123 {
124 base.Destroy();
125
123 DetailLog("{0},BSCharacter.Destroy", LocalID); 126 DetailLog("{0},BSCharacter.Destroy", LocalID);
124 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 127 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
125 { 128 {
126 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); 129 PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
127 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); 130 PhysBody.Clear();
131 PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */);
132 PhysShape.Clear();
128 }); 133 });
129 } 134 }
130 135
131 private void SetPhysicalProperties() 136 private void SetPhysicalProperties()
132 { 137 {
133 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); 138 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody);
134 139
135 ZeroMotion(true); 140 ZeroMotion(true);
136 ForcePosition = _position; 141 ForcePosition = _position;
142
137 // Set the velocity and compute the proper friction 143 // Set the velocity and compute the proper friction
144 _velocityMotor.Reset();
145 _velocityMotor.SetTarget(_velocity);
146 _velocityMotor.SetCurrent(_velocity);
138 ForceVelocity = _velocity; 147 ForceVelocity = _velocity;
139 148
140 // This will enable or disable the flying buoyancy of the avatar. 149 // This will enable or disable the flying buoyancy of the avatar.
141 // Needs to be reset especially when an avatar is recreated after crossing a region boundry. 150 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
142 Flying = _flying; 151 Flying = _flying;
143 152
144 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); 153 PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution);
145 BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); 154 PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin);
146 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); 155 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale);
147 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); 156 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
148 if (PhysicsScene.Params.ccdMotionThreshold > 0f) 157 if (BSParam.CcdMotionThreshold > 0f)
149 { 158 {
150 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); 159 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
151 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); 160 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
152 } 161 }
153 162
154 UpdatePhysicalMassProperties(RawMass); 163 UpdatePhysicalMassProperties(RawMass, false);
155 164
156 // Make so capsule does not fall over 165 // Make so capsule does not fall over
157 BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); 166 PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
158 167
159 BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); 168 PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
160 169
161 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); 170 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody);
162 171
163 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); 172 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
164 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION); 173 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION);
165 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); 174 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody);
166 175
167 // Do this after the object has been added to the world 176 // Do this after the object has been added to the world
168 BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, 177 PhysBody.collisionType = CollisionType.Avatar;
169 (uint)CollisionFilterGroups.AvatarFilter, 178 PhysBody.ApplyCollisionMask(PhysicsScene);
170 (uint)CollisionFilterGroups.AvatarMask); 179 }
180
181 // The avatar's movement is controlled by this motor that speeds up and slows down
182 // the avatar seeking to reach the motor's target speed.
183 // This motor runs as a prestep action for the avatar so it will keep the avatar
184 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
185 private void SetupMovementMotor()
186 {
187 // Infinite decay and timescale values so motor only changes current to target values.
188 _velocityMotor = new BSVMotor("BSCharacter.Velocity",
189 0.2f, // time scale
190 BSMotor.Infinite, // decay time scale
191 BSMotor.InfiniteVector, // friction timescale
192 1f // efficiency
193 );
194 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
195
196 RegisterPreStepAction("BSCharactor.Movement", LocalID, delegate(float timeStep)
197 {
198 // TODO: Decide if the step parameters should be changed depending on the avatar's
199 // state (flying, colliding, ...). There is code in ODE to do this.
200
201 // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
202 // specified for the avatar is the one that should be used. For falling, if the avatar
203 // is not flying and is not colliding then it is presumed to be falling and the Z
204 // component is not fooled with (thus allowing gravity to do its thing).
205 // When the avatar is standing, though, the user has specified a velocity of zero and
206 // the avatar should be standing. But if the avatar is pushed by something in the world
207 // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
208 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
209 // errors can creap in and the avatar will slowly float off in some direction.
210 // So, the problem is that, when an avatar is standing, we cannot tell creaping error
211 // from real pushing.OMV.Vector3.Zero;
212 // The code below keeps setting the velocity to zero hoping the world will keep pushing.
213
214 _velocityMotor.Step(timeStep);
215
216 // If we're not supposed to be moving, make sure things are zero.
217 if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero && IsColliding)
218 {
219 // The avatar shouldn't be moving
220 _velocityMotor.Zero();
221
222 // If we are colliding with a stationary object, presume we're standing and don't move around
223 if (!ColliderIsMoving)
224 {
225 DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID);
226 ZeroMotion(true /* inTaintTime */);
227 }
228
229 // Standing has more friction on the ground
230 if (_currentFriction != BSParam.AvatarStandingFriction)
231 {
232 _currentFriction = BSParam.AvatarStandingFriction;
233 PhysicsScene.PE.SetFriction(PhysBody, _currentFriction);
234 }
235 DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1}", LocalID, _velocityMotor.TargetValue);
236 }
237 else
238 {
239 OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue;
240
241 if (_currentFriction != BSParam.AvatarFriction)
242 {
243 // Probably starting up walking. Set friction to moving friction.
244 _currentFriction = BSParam.AvatarFriction;
245 PhysicsScene.PE.SetFriction(PhysBody, _currentFriction);
246 }
247
248 // If falling, we keep the world's downward vector no matter what the other axis specify.
249 if (!Flying && !IsColliding)
250 {
251 stepVelocity.Z = _velocity.Z;
252 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
253 }
254
255 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
256 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass;
257
258 // Should we check for move force being small and forcing velocity to zero?
259
260 // Add special movement force to allow avatars to walk up stepped surfaces.
261 moveForce += WalkUpStairs();
262
263 DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
264 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
265 }
266 });
267 }
268
269 // Decide of the character is colliding with a low object and compute a force to pop the
270 // avatar up so it has a chance of walking up and over the low object.
271 private OMV.Vector3 WalkUpStairs()
272 {
273 OMV.Vector3 ret = OMV.Vector3.Zero;
274
275 // This test is done if moving forward, not flying and is colliding with something.
276 // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
277 // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
278 if (IsColliding && !Flying && TargetSpeed > 0.1f /* && ForwardSpeed < 0.1f */)
279 {
280 // The range near the character's feet where we will consider stairs
281 float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
282 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
283
284 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is
285 foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList)
286 {
287 // Don't care about collisions with the terrain
288 if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID)
289 {
290 OMV.Vector3 touchPosition = kvp.Value.Position;
291 // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
292 // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
293 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
294 {
295 // This contact is within the 'near the feet' range.
296 // The normal should be our contact point to the object so it is pointing away
297 // thus the difference between our facing orientation and the normal should be small.
298 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation;
299 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
300 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
301 if (diff < BSParam.AvatarStepApproachFactor)
302 {
303 // Found the stairs contact point. Push up a little to raise the character.
304 float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor;
305 ret = new OMV.Vector3(0f, 0f, upForce);
306
307 // Also move the avatar up for the new height
308 OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
309 ForcePosition = RawPosition + displacement;
310 }
311 DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
312 LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
313 }
314 }
315 }
316 }
317
318 return ret;
171 } 319 }
172 320
173 public override void RequestPhysicsterseUpdate() 321 public override void RequestPhysicsterseUpdate()
@@ -185,24 +333,31 @@ public sealed class BSCharacter : BSPhysObject
185 } 333 }
186 334
187 set { 335 set {
188 // When an avatar's size is set, only the height is changed.
189 _size = value; 336 _size = value;
190 ComputeAvatarScale(_size); 337 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
338 // replace with the default values.
339 if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth;
340 if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth;
341
342 Scale = ComputeAvatarScale(_size);
191 ComputeAvatarVolumeAndMass(); 343 ComputeAvatarVolumeAndMass();
192 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", 344 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
193 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); 345 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
194 346
195 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() 347 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
196 { 348 {
197 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); 349 if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
198 UpdatePhysicalMassProperties(RawMass); 350 {
351 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale);
352 UpdatePhysicalMassProperties(RawMass, true);
353 // Make sure this change appears as a property update event
354 PhysicsScene.PE.PushUpdate(PhysBody);
355 }
199 }); 356 });
200 357
201 } 358 }
202 } 359 }
203 360
204 public override OMV.Vector3 Scale { get; set; }
205
206 public override PrimitiveBaseShape Shape 361 public override PrimitiveBaseShape Shape
207 { 362 {
208 set { BaseShape = value; } 363 set { BaseShape = value; }
@@ -219,6 +374,10 @@ public sealed class BSCharacter : BSPhysObject
219 public override bool Selected { 374 public override bool Selected {
220 set { _selected = value; } 375 set { _selected = value; }
221 } 376 }
377 public override bool IsSelected
378 {
379 get { return _selected; }
380 }
222 public override void CrossingFailure() { return; } 381 public override void CrossingFailure() { return; }
223 public override void link(PhysicsActor obj) { return; } 382 public override void link(PhysicsActor obj) { return; }
224 public override void delink() { return; } 383 public override void delink() { return; }
@@ -236,7 +395,8 @@ public sealed class BSCharacter : BSPhysObject
236 // Zero some other properties directly into the physics engine 395 // Zero some other properties directly into the physics engine
237 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 396 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
238 { 397 {
239 BulletSimAPI.ClearAllForces2(PhysBody.ptr); 398 if (PhysBody.HasPhysicalBody)
399 PhysicsScene.PE.ClearAllForces(PhysBody);
240 }); 400 });
241 } 401 }
242 public override void ZeroAngularMotion(bool inTaintTime) 402 public override void ZeroAngularMotion(bool inTaintTime)
@@ -245,10 +405,13 @@ public sealed class BSCharacter : BSPhysObject
245 405
246 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 406 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
247 { 407 {
248 BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); 408 if (PhysBody.HasPhysicalBody)
249 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); 409 {
250 // The next also get rid of applied linear force but the linear velocity is untouched. 410 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero);
251 BulletSimAPI.ClearForces2(PhysBody.ptr); 411 PhysicsScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero);
412 // The next also get rid of applied linear force but the linear velocity is untouched.
413 PhysicsScene.PE.ClearForces(PhysBody);
414 }
252 }); 415 });
253 } 416 }
254 417
@@ -263,29 +426,31 @@ public sealed class BSCharacter : BSPhysObject
263 public override OMV.Vector3 Position { 426 public override OMV.Vector3 Position {
264 get { 427 get {
265 // Don't refetch the position because this function is called a zillion times 428 // Don't refetch the position because this function is called a zillion times
266 // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); 429 // _position = PhysicsScene.PE.GetObjectPosition(Scene.World, LocalID);
267 return _position; 430 return _position;
268 } 431 }
269 set { 432 set {
270 _position = value; 433 _position = value;
271 PositionSanityCheck();
272 434
273 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 435 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
274 { 436 {
275 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 437 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
276 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 438 ForcePosition = _position;
277 }); 439 });
278 } 440 }
279 } 441 }
280 public override OMV.Vector3 ForcePosition { 442 public override OMV.Vector3 ForcePosition {
281 get { 443 get {
282 _position = BulletSimAPI.GetPosition2(PhysBody.ptr); 444 _position = PhysicsScene.PE.GetPosition(PhysBody);
283 return _position; 445 return _position;
284 } 446 }
285 set { 447 set {
286 _position = value; 448 _position = value;
287 PositionSanityCheck(); 449 if (PhysBody.HasPhysicalBody)
288 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 450 {
451 PositionSanityCheck();
452 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
453 }
289 } 454 }
290 } 455 }
291 456
@@ -297,8 +462,17 @@ public sealed class BSCharacter : BSPhysObject
297 { 462 {
298 bool ret = false; 463 bool ret = false;
299 464
465 // TODO: check for out of bounds
466 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
467 {
468 // The character is out of the known/simulated area.
469 // Upper levels of code will handle the transition to other areas so, for
470 // the time, we just ignore the position.
471 return ret;
472 }
473
300 // If below the ground, move the avatar up 474 // If below the ground, move the avatar up
301 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); 475 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
302 if (Position.Z < terrainHeight) 476 if (Position.Z < terrainHeight)
303 { 477 {
304 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 478 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
@@ -307,7 +481,7 @@ public sealed class BSCharacter : BSPhysObject
307 } 481 }
308 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 482 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
309 { 483 {
310 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); 484 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
311 if (Position.Z < waterHeight) 485 if (Position.Z < waterHeight)
312 { 486 {
313 _position.Z = waterHeight; 487 _position.Z = waterHeight;
@@ -315,7 +489,6 @@ public sealed class BSCharacter : BSPhysObject
315 } 489 }
316 } 490 }
317 491
318 // TODO: check for out of bounds
319 return ret; 492 return ret;
320 } 493 }
321 494
@@ -332,7 +505,8 @@ public sealed class BSCharacter : BSPhysObject
332 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() 505 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
333 { 506 {
334 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 507 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
335 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 508 if (PhysBody.HasPhysicalBody)
509 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
336 }); 510 });
337 ret = true; 511 ret = true;
338 } 512 }
@@ -345,10 +519,10 @@ public sealed class BSCharacter : BSPhysObject
345 public override float RawMass { 519 public override float RawMass {
346 get {return _mass; } 520 get {return _mass; }
347 } 521 }
348 public override void UpdatePhysicalMassProperties(float physMass) 522 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
349 { 523 {
350 OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); 524 OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass);
351 BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); 525 PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia);
352 } 526 }
353 527
354 public override OMV.Vector3 Force { 528 public override OMV.Vector3 Force {
@@ -359,7 +533,8 @@ public sealed class BSCharacter : BSPhysObject
359 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() 533 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
360 { 534 {
361 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); 535 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
362 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); 536 if (PhysBody.HasPhysicalBody)
537 PhysicsScene.PE.SetObjectForce(PhysBody, _force);
363 }); 538 });
364 } 539 }
365 } 540 }
@@ -376,6 +551,37 @@ public sealed class BSCharacter : BSPhysObject
376 551
377 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } 552 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
378 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } 553 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
554
555 // Sets the target in the motor. This starts the changing of the avatar's velocity.
556 public override OMV.Vector3 TargetVelocity
557 {
558 get
559 {
560 return m_targetVelocity;
561 }
562 set
563 {
564 DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value);
565 m_targetVelocity = value;
566 OMV.Vector3 targetVel = value;
567 if (_setAlwaysRun)
568 targetVel *= BSParam.AvatarAlwaysRunFactor;
569
570 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate()
571 {
572 _velocityMotor.Reset();
573 _velocityMotor.SetTarget(targetVel);
574 _velocityMotor.SetCurrent(_velocity);
575 _velocityMotor.Enabled = true;
576 });
577 }
578 }
579 public override OMV.Vector3 RawVelocity
580 {
581 get { return _velocity; }
582 set { _velocity = value; }
583 }
584 // Directly setting velocity means this is what the user really wants now.
379 public override OMV.Vector3 Velocity { 585 public override OMV.Vector3 Velocity {
380 get { return _velocity; } 586 get { return _velocity; }
381 set { 587 set {
@@ -383,6 +589,11 @@ public sealed class BSCharacter : BSPhysObject
383 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 589 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
384 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 590 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
385 { 591 {
592 _velocityMotor.Reset();
593 _velocityMotor.SetCurrent(_velocity);
594 _velocityMotor.SetTarget(_velocity);
595 _velocityMotor.Enabled = false;
596
386 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 597 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
387 ForceVelocity = _velocity; 598 ForceVelocity = _velocity;
388 }); 599 });
@@ -391,30 +602,11 @@ public sealed class BSCharacter : BSPhysObject
391 public override OMV.Vector3 ForceVelocity { 602 public override OMV.Vector3 ForceVelocity {
392 get { return _velocity; } 603 get { return _velocity; }
393 set { 604 set {
394 // Depending on whether the avatar is moving or not, change the friction 605 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity");
395 // to keep the avatar from slipping around
396 if (_velocity.Length() == 0)
397 {
398 if (_currentFriction != PhysicsScene.Params.avatarStandingFriction)
399 {
400 _currentFriction = PhysicsScene.Params.avatarStandingFriction;
401 BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
402 }
403 }
404 else
405 {
406 if (_currentFriction != PhysicsScene.Params.avatarFriction)
407 {
408 _currentFriction = PhysicsScene.Params.avatarFriction;
409 BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
410 }
411 }
412 _velocity = value;
413 // Remember the set velocity so we can suppress the reduction by friction, ...
414 _appliedVelocity = value;
415 606
416 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); 607 _velocity = value;
417 BulletSimAPI.Activate2(PhysBody.ptr, true); 608 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
609 PhysicsScene.PE.Activate(PhysBody, true);
418 } 610 }
419 } 611 }
420 public override OMV.Vector3 Torque { 612 public override OMV.Vector3 Torque {
@@ -439,13 +631,16 @@ public sealed class BSCharacter : BSPhysObject
439 public override OMV.Quaternion Orientation { 631 public override OMV.Quaternion Orientation {
440 get { return _orientation; } 632 get { return _orientation; }
441 set { 633 set {
442 _orientation = value; 634 // Orientation is set zillions of times when an avatar is walking. It's like
443 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 635 // the viewer doesn't trust us.
444 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() 636 if (_orientation != value)
445 { 637 {
446 // _position = BulletSimAPI.GetPosition2(BSBody.ptr); 638 _orientation = value;
447 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 639 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
448 }); 640 {
641 ForceOrientation = _orientation;
642 });
643 }
449 } 644 }
450 } 645 }
451 // Go directly to Bullet to get/set the value. 646 // Go directly to Bullet to get/set the value.
@@ -453,13 +648,17 @@ public sealed class BSCharacter : BSPhysObject
453 { 648 {
454 get 649 get
455 { 650 {
456 _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); 651 _orientation = PhysicsScene.PE.GetOrientation(PhysBody);
457 return _orientation; 652 return _orientation;
458 } 653 }
459 set 654 set
460 { 655 {
461 _orientation = value; 656 _orientation = value;
462 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 657 if (PhysBody.HasPhysicalBody)
658 {
659 // _position = PhysicsScene.PE.GetPosition(BSBody);
660 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
661 }
463 } 662 }
464 } 663 }
465 public override int PhysicsActorType { 664 public override int PhysicsActorType {
@@ -478,10 +677,14 @@ public sealed class BSCharacter : BSPhysObject
478 public override bool IsStatic { 677 public override bool IsStatic {
479 get { return false; } 678 get { return false; }
480 } 679 }
680 public override bool IsPhysicallyActive {
681 get { return true; }
682 }
481 public override bool Flying { 683 public override bool Flying {
482 get { return _flying; } 684 get { return _flying; }
483 set { 685 set {
484 _flying = value; 686 _flying = value;
687
485 // simulate flying by changing the effect of gravity 688 // simulate flying by changing the effect of gravity
486 Buoyancy = ComputeBuoyancyFromFlying(_flying); 689 Buoyancy = ComputeBuoyancyFromFlying(_flying);
487 } 690 }
@@ -500,27 +703,18 @@ public sealed class BSCharacter : BSPhysObject
500 get { return _throttleUpdates; } 703 get { return _throttleUpdates; }
501 set { _throttleUpdates = value; } 704 set { _throttleUpdates = value; }
502 } 705 }
503 public override bool IsColliding {
504 get { return (CollidingStep == PhysicsScene.SimulationStep); }
505 set { _isColliding = value; }
506 }
507 public override bool CollidingGround {
508 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
509 set { CollidingGround = value; }
510 }
511 public override bool CollidingObj {
512 get { return _collidingObj; }
513 set { _collidingObj = value; }
514 }
515 public override bool FloatOnWater { 706 public override bool FloatOnWater {
516 set { 707 set {
517 _floatOnWater = value; 708 _floatOnWater = value;
518 PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() 709 PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
519 { 710 {
520 if (_floatOnWater) 711 if (PhysBody.HasPhysicalBody)
521 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); 712 {
522 else 713 if (_floatOnWater)
523 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); 714 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
715 else
716 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
717 }
524 }); 718 });
525 } 719 }
526 } 720 }
@@ -549,11 +743,15 @@ public sealed class BSCharacter : BSPhysObject
549 } 743 }
550 public override float ForceBuoyancy { 744 public override float ForceBuoyancy {
551 get { return _buoyancy; } 745 get { return _buoyancy; }
552 set { _buoyancy = value; 746 set {
747 PhysicsScene.AssertInTaintTime("BSCharacter.ForceBuoyancy");
748
749 _buoyancy = value;
553 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 750 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
554 // Buoyancy is faked by changing the gravity applied to the object 751 // Buoyancy is faked by changing the gravity applied to the object
555 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); 752 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
556 BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); 753 if (PhysBody.HasPhysicalBody)
754 PhysicsScene.PE.SetGravity(PhysBody, new OMV.Vector3(0f, 0f, grav));
557 } 755 }
558 } 756 }
559 757
@@ -589,24 +787,40 @@ public sealed class BSCharacter : BSPhysObject
589 public override float APIDStrength { set { return; } } 787 public override float APIDStrength { set { return; } }
590 public override float APIDDamping { set { return; } } 788 public override float APIDDamping { set { return; } }
591 789
592 public override void AddForce(OMV.Vector3 force, bool pushforce) { 790 public override void AddForce(OMV.Vector3 force, bool pushforce)
791 {
792 // Since this force is being applied in only one step, make this a force per second.
793 OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep;
794 AddForce(addForce, pushforce, false);
795 }
796 private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
593 if (force.IsFinite()) 797 if (force.IsFinite())
594 { 798 {
595 _force.X += force.X; 799 float magnitude = force.Length();
596 _force.Y += force.Y; 800 if (magnitude > BSParam.MaxAddForceMagnitude)
597 _force.Z += force.Z;
598 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
599 PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate()
600 { 801 {
601 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); 802 // Force has a limit
602 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); 803 force = force / magnitude * BSParam.MaxAddForceMagnitude;
804 }
805
806 OMV.Vector3 addForce = force;
807 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce);
808
809 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate()
810 {
811 // Bullet adds this central force to the total force for this tick
812 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
813 if (PhysBody.HasPhysicalBody)
814 {
815 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce);
816 }
603 }); 817 });
604 } 818 }
605 else 819 else
606 { 820 {
607 m_log.ErrorFormat("{0}: Got a NaN force applied to a Character", LogHeader); 821 m_log.WarnFormat("{0}: Got a NaN force applied to a character. LocalID={1}", LogHeader, LocalID);
822 return;
608 } 823 }
609 //m_lastUpdateSent = false;
610 } 824 }
611 825
612 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 826 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
@@ -614,24 +828,31 @@ public sealed class BSCharacter : BSPhysObject
614 public override void SetMomentum(OMV.Vector3 momentum) { 828 public override void SetMomentum(OMV.Vector3 momentum) {
615 } 829 }
616 830
617 private void ComputeAvatarScale(OMV.Vector3 size) 831 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size)
618 { 832 {
619 // The 'size' given by the simulator is the mid-point of the avatar 833 OMV.Vector3 newScale;
620 // and X and Y are unspecified. 834
621 835 // Bullet's capsule total height is the "passed height + radius * 2";
622 OMV.Vector3 newScale = size; 836 // The base capsule is 1 diameter and 2 height (passed radius=0.5, passed height = 1)
623 // newScale.X = PhysicsScene.Params.avatarCapsuleWidth; 837 // The number we pass in for 'scaling' is the multiplier to get that base
624 // newScale.Y = PhysicsScene.Params.avatarCapsuleDepth; 838 // shape to be the size desired.
625 839 // So, when creating the scale for the avatar height, we take the passed height
626 // From the total height, remove the capsule half spheres that are at each end 840 // (size.Z) and remove the caps.
627 // The 1.15f came from ODE. Not sure what this factors in. 841 // Another oddity of the Bullet capsule implementation is that it presumes the Y
628 // newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y); 842 // dimension is the radius of the capsule. Even though some of the code allows
843 // for a asymmetrical capsule, other parts of the code presume it is cylindrical.
844
845 // Scale is multiplier of radius with one of "0.5"
846 newScale.X = size.X / 2f;
847 newScale.Y = size.Y / 2f;
629 848
630 // The total scale height is the central cylindar plus the caps on the two ends. 849 // The total scale height is the central cylindar plus the caps on the two ends.
631 newScale.Z = size.Z + (Math.Min(size.X, size.Y) * 2f); 850 newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2)) / 2f;
851 // If smaller than the endcaps, just fake like we're almost that small
852 if (newScale.Z < 0)
853 newScale.Z = 0.1f;
632 854
633 // Convert diameters to radii and height to half height -- the way Bullet expects it. 855 return newScale;
634 Scale = newScale / 2f;
635 } 856 }
636 857
637 // set _avatarVolume and _mass based on capsule size, _density and Scale 858 // set _avatarVolume and _mass based on capsule size, _density and Scale
@@ -639,14 +860,14 @@ public sealed class BSCharacter : BSPhysObject
639 { 860 {
640 _avatarVolume = (float)( 861 _avatarVolume = (float)(
641 Math.PI 862 Math.PI
642 * Scale.X 863 * Size.X / 2f
643 * Scale.Y // the area of capsule cylinder 864 * Size.Y / 2f // the area of capsule cylinder
644 * Scale.Z // times height of capsule cylinder 865 * Size.Z // times height of capsule cylinder
645 + 1.33333333f 866 + 1.33333333f
646 * Math.PI 867 * Math.PI
647 * Scale.X 868 * Size.X / 2f
648 * Math.Min(Scale.X, Scale.Y) 869 * Math.Min(Size.X, Size.Y) / 2
649 * Scale.Y // plus the volume of the capsule end caps 870 * Size.Y / 2f // plus the volume of the capsule end caps
650 ); 871 );
651 _mass = _avatarDensity * _avatarVolume; 872 _mass = _avatarDensity * _avatarVolume;
652 } 873 }
@@ -657,27 +878,29 @@ public sealed class BSCharacter : BSPhysObject
657 { 878 {
658 _position = entprop.Position; 879 _position = entprop.Position;
659 _orientation = entprop.Rotation; 880 _orientation = entprop.Rotation;
660 _velocity = entprop.Velocity; 881
882 // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar
883 // and will send agent updates to the clients if velocity changes by more than
884 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many
885 // extra updates.
886 if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f))
887 _velocity = entprop.Velocity;
888
661 _acceleration = entprop.Acceleration; 889 _acceleration = entprop.Acceleration;
662 _rotationalVelocity = entprop.RotationalVelocity; 890 _rotationalVelocity = entprop.RotationalVelocity;
891
663 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. 892 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
664 PositionSanityCheck(true); 893 if (PositionSanityCheck(true))
894 {
895 entprop.Position = _position;
896 }
665 897
666 // remember the current and last set values 898 // remember the current and last set values
667 LastEntityProperties = CurrentEntityProperties; 899 LastEntityProperties = CurrentEntityProperties;
668 CurrentEntityProperties = entprop; 900 CurrentEntityProperties = entprop;
669 901
670 if (entprop.Velocity != LastEntityProperties.Velocity)
671 {
672 // Changes in the velocity are suppressed in avatars.
673 // That's just the way they are defined.
674 OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z);
675 _velocity = avVel;
676 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel);
677 }
678
679 // Tell the linkset about value changes 902 // Tell the linkset about value changes
680 Linkset.UpdateProperties(this); 903 Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
681 904
682 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 905 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
683 // base.RequestPhysicsterseUpdate(); 906 // base.RequestPhysicsterseUpdate();
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 65fac00..b813974 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -36,7 +36,8 @@ public abstract class BSConstraint : IDisposable
36{ 36{
37 private static string LogHeader = "[BULLETSIM CONSTRAINT]"; 37 private static string LogHeader = "[BULLETSIM CONSTRAINT]";
38 38
39 protected BulletSim m_world; 39 protected BulletWorld m_world;
40 protected BSScene PhysicsScene;
40 protected BulletBody m_body1; 41 protected BulletBody m_body1;
41 protected BulletBody m_body2; 42 protected BulletBody m_body2;
42 protected BulletConstraint m_constraint; 43 protected BulletConstraint m_constraint;
@@ -48,8 +49,10 @@ public abstract class BSConstraint : IDisposable
48 public abstract ConstraintType Type { get; } 49 public abstract ConstraintType Type { get; }
49 public bool IsEnabled { get { return m_enabled; } } 50 public bool IsEnabled { get { return m_enabled; } }
50 51
51 public BSConstraint() 52 public BSConstraint(BulletWorld world)
52 { 53 {
54 m_world = world;
55 PhysicsScene = m_world.physicsScene;
53 } 56 }
54 57
55 public virtual void Dispose() 58 public virtual void Dispose()
@@ -57,15 +60,15 @@ public abstract class BSConstraint : IDisposable
57 if (m_enabled) 60 if (m_enabled)
58 { 61 {
59 m_enabled = false; 62 m_enabled = false;
60 if (m_constraint.ptr != IntPtr.Zero) 63 if (m_constraint.HasPhysicalConstraint)
61 { 64 {
62 bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); 65 bool success = PhysicsScene.PE.DestroyConstraint(m_world, m_constraint);
63 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", 66 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
64 BSScene.DetailLogZero, 67 BSScene.DetailLogZero,
65 m_body1.ID, m_body1.ptr.ToString("X"), 68 m_body1.ID, m_body1.AddrString,
66 m_body2.ID, m_body2.ptr.ToString("X"), 69 m_body2.ID, m_body2.AddrString,
67 success); 70 success);
68 m_constraint.ptr = System.IntPtr.Zero; 71 m_constraint.Clear();
69 } 72 }
70 } 73 }
71 } 74 }
@@ -74,7 +77,7 @@ public abstract class BSConstraint : IDisposable
74 { 77 {
75 bool ret = false; 78 bool ret = false;
76 if (m_enabled) 79 if (m_enabled)
77 ret = BulletSimAPI.SetLinearLimits2(m_constraint.ptr, low, high); 80 ret = PhysicsScene.PE.SetLinearLimits(m_constraint, low, high);
78 return ret; 81 return ret;
79 } 82 }
80 83
@@ -82,7 +85,7 @@ public abstract class BSConstraint : IDisposable
82 { 85 {
83 bool ret = false; 86 bool ret = false;
84 if (m_enabled) 87 if (m_enabled)
85 ret = BulletSimAPI.SetAngularLimits2(m_constraint.ptr, low, high); 88 ret = PhysicsScene.PE.SetAngularLimits(m_constraint, low, high);
86 return ret; 89 return ret;
87 } 90 }
88 91
@@ -91,7 +94,7 @@ public abstract class BSConstraint : IDisposable
91 bool ret = false; 94 bool ret = false;
92 if (m_enabled) 95 if (m_enabled)
93 { 96 {
94 BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.ptr, cnt); 97 PhysicsScene.PE.SetConstraintNumSolverIterations(m_constraint, cnt);
95 ret = true; 98 ret = true;
96 } 99 }
97 return ret; 100 return ret;
@@ -103,7 +106,7 @@ public abstract class BSConstraint : IDisposable
103 if (m_enabled) 106 if (m_enabled)
104 { 107 {
105 // Recompute the internal transforms 108 // Recompute the internal transforms
106 BulletSimAPI.CalculateTransforms2(m_constraint.ptr); 109 PhysicsScene.PE.CalculateTransforms(m_constraint);
107 ret = true; 110 ret = true;
108 } 111 }
109 return ret; 112 return ret;
@@ -122,7 +125,7 @@ public abstract class BSConstraint : IDisposable
122 // Setting an object's mass to zero (making it static like when it's selected) 125 // Setting an object's mass to zero (making it static like when it's selected)
123 // automatically disables the constraints. 126 // automatically disables the constraints.
124 // If the link is enabled, be sure to set the constraint itself to enabled. 127 // 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)); 128 PhysicsScene.PE.SetConstraintEnable(m_constraint, BSParam.NumericBool(true));
126 } 129 }
127 else 130 else
128 { 131 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
index 23ef052..ecb1b32 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
@@ -39,51 +39,49 @@ public sealed class BSConstraint6Dof : BSConstraint
39 public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } 39 public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
40 40
41 // Create a btGeneric6DofConstraint 41 // Create a btGeneric6DofConstraint
42 public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, 42 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
43 Vector3 frame1, Quaternion frame1rot, 43 Vector3 frame1, Quaternion frame1rot,
44 Vector3 frame2, Quaternion frame2rot, 44 Vector3 frame2, Quaternion frame2rot,
45 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 45 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
46 : base(world)
46 { 47 {
47 m_world = world;
48 m_body1 = obj1; 48 m_body1 = obj1;
49 m_body2 = obj2; 49 m_body2 = obj2;
50 m_constraint = new BulletConstraint( 50 m_constraint = PhysicsScene.PE.Create6DofConstraint(m_world, m_body1, m_body2,
51 BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr,
52 frame1, frame1rot, 51 frame1, frame1rot,
53 frame2, frame2rot, 52 frame2, frame2rot,
54 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 53 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
55 m_enabled = true; 54 m_enabled = true;
56 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", 55 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
57 BSScene.DetailLogZero, world.worldID, 56 BSScene.DetailLogZero, world.worldID,
58 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); 57 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
59 } 58 }
60 59
61 public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, 60 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
62 Vector3 joinPoint, 61 Vector3 joinPoint,
63 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 62 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
63 : base(world)
64 { 64 {
65 m_world = world;
66 m_body1 = obj1; 65 m_body1 = obj1;
67 m_body2 = obj2; 66 m_body2 = obj2;
68 if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) 67 if (!obj1.HasPhysicalBody || !obj2.HasPhysicalBody)
69 { 68 {
70 world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", 69 world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
71 BSScene.DetailLogZero, world.worldID, 70 BSScene.DetailLogZero, world.worldID,
72 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); 71 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
73 world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", 72 world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
74 LogHeader, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); 73 LogHeader, world.worldID, obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
75 m_enabled = false; 74 m_enabled = false;
76 } 75 }
77 else 76 else
78 { 77 {
79 m_constraint = new BulletConstraint( 78 m_constraint = PhysicsScene.PE.Create6DofConstraintToPoint(m_world, m_body1, m_body2,
80 BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr,
81 joinPoint, 79 joinPoint,
82 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 80 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
83 world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", 81 PhysicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
84 BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), 82 BSScene.DetailLogZero, world.worldID, m_constraint.AddrString,
85 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); 83 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
86 if (m_constraint.ptr == IntPtr.Zero) 84 if (!m_constraint.HasPhysicalConstraint)
87 { 85 {
88 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", 86 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
89 LogHeader, obj1.ID, obj2.ID); 87 LogHeader, obj1.ID, obj2.ID);
@@ -101,7 +99,7 @@ public sealed class BSConstraint6Dof : BSConstraint
101 bool ret = false; 99 bool ret = false;
102 if (m_enabled) 100 if (m_enabled)
103 { 101 {
104 BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); 102 PhysicsScene.PE.SetFrames(m_constraint, frameA, frameArot, frameB, frameBrot);
105 ret = true; 103 ret = true;
106 } 104 }
107 return ret; 105 return ret;
@@ -112,9 +110,9 @@ public sealed class BSConstraint6Dof : BSConstraint
112 bool ret = false; 110 bool ret = false;
113 if (m_enabled) 111 if (m_enabled)
114 { 112 {
115 BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); 113 PhysicsScene.PE.SetConstraintParam(m_constraint, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
116 BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); 114 PhysicsScene.PE.SetConstraintParam(m_constraint, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
117 BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); 115 PhysicsScene.PE.SetConstraintParam(m_constraint, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
118 ret = true; 116 ret = true;
119 } 117 }
120 return ret; 118 return ret;
@@ -125,7 +123,7 @@ public sealed class BSConstraint6Dof : BSConstraint
125 bool ret = false; 123 bool ret = false;
126 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; 124 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
127 if (m_enabled) 125 if (m_enabled)
128 ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); 126 ret = PhysicsScene.PE.UseFrameOffset(m_constraint, onOff);
129 return ret; 127 return ret;
130 } 128 }
131 129
@@ -135,7 +133,7 @@ public sealed class BSConstraint6Dof : BSConstraint
135 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; 133 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
136 if (m_enabled) 134 if (m_enabled)
137 { 135 {
138 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); 136 ret = PhysicsScene.PE.TranslationalLimitMotor(m_constraint, onOff, targetVelocity, maxMotorForce);
139 m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", 137 m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}",
140 BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); 138 BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce);
141 } 139 }
@@ -146,7 +144,7 @@ public sealed class BSConstraint6Dof : BSConstraint
146 { 144 {
147 bool ret = false; 145 bool ret = false;
148 if (m_enabled) 146 if (m_enabled)
149 ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); 147 ret = PhysicsScene.PE.SetBreakingImpulseThreshold(m_constraint, threshold);
150 return ret; 148 return ret;
151 } 149 }
152} 150}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
index a9fd826..2aeff25 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -41,9 +41,9 @@ public sealed class BSConstraintCollection : IDisposable
41 delegate bool ConstraintAction(BSConstraint constrain); 41 delegate bool ConstraintAction(BSConstraint constrain);
42 42
43 private List<BSConstraint> m_constraints; 43 private List<BSConstraint> m_constraints;
44 private BulletSim m_world; 44 private BulletWorld m_world;
45 45
46 public BSConstraintCollection(BulletSim world) 46 public BSConstraintCollection(BulletWorld world)
47 { 47 {
48 m_world = world; 48 m_world = world;
49 m_constraints = new List<BSConstraint>(); 49 m_constraints = new List<BSConstraint>();
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
index ed3ffa7..7714a03 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
@@ -36,19 +36,17 @@ public sealed class BSConstraintHinge : BSConstraint
36{ 36{
37 public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } 37 public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } }
38 38
39 public BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2, 39 public BSConstraintHinge(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 pivotInA, Vector3 pivotInB, 40 Vector3 pivotInA, Vector3 pivotInB,
41 Vector3 axisInA, Vector3 axisInB, 41 Vector3 axisInA, Vector3 axisInB,
42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
43 : base(world)
43 { 44 {
44 m_world = world;
45 m_body1 = obj1; 45 m_body1 = obj1;
46 m_body2 = obj2; 46 m_body2 = obj2;
47 m_constraint = new BulletConstraint( 47 m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2,
48 BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, 48 pivotInA, pivotInB, axisInA, axisInB,
49 pivotInA, pivotInB, 49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
50 axisInA, axisInB,
51 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
52 m_enabled = true; 50 m_enabled = true;
53 } 51 }
54 52
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index dbc9039..b51e9fd 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -24,28 +24,16 @@
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 * The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial
28/* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to 28 * are Copyright (c) 2009 Linden Research, Inc and are used under their license
29 * call the BulletSim system. 29 * of Creative Commons Attribution-Share Alike 3.0
30 */ 30 * (http://creativecommons.org/licenses/by-sa/3.0/).
31/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
32 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
33 * ODEPrim.cs contains methods dealing with Prim editing, Prim
34 * characteristics and Kinetic motion.
35 * ODEDynamics.cs contains methods dealing with Prim Physical motion
36 * (dynamics) and the associated settings. Old Linear and angular
37 * motors for dynamic motion have been replace with MoveLinear()
38 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
39 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
40 * switch between 'VEHICLE' parameter use and general dynamics
41 * settings use.
42 */ 31 */
43 32
44using System; 33using System;
45using System.Collections.Generic; 34using System.Collections.Generic;
46using System.Reflection; 35using System.Reflection;
47using System.Runtime.InteropServices; 36using System.Runtime.InteropServices;
48using log4net;
49using OpenMetaverse; 37using OpenMetaverse;
50using OpenSim.Framework; 38using OpenSim.Framework;
51using OpenSim.Region.Physics.Manager; 39using OpenSim.Region.Physics.Manager;
@@ -80,10 +68,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
80 private Quaternion m_referenceFrame = Quaternion.Identity; 68 private Quaternion m_referenceFrame = Quaternion.Identity;
81 69
82 // Linear properties 70 // Linear properties
71 private BSVMotor m_linearMotor = new BSVMotor("LinearMotor");
83 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time 72 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
84 private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center 73 private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center
85 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL 74 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
86 private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body
87 private Vector3 m_linearFrictionTimescale = Vector3.Zero; 75 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
88 private float m_linearMotorDecayTimescale = 0; 76 private float m_linearMotorDecayTimescale = 0;
89 private float m_linearMotorTimescale = 0; 77 private float m_linearMotorTimescale = 0;
@@ -93,16 +81,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
93 // private Vector3 m_linearMotorOffset = Vector3.Zero; 81 // private Vector3 m_linearMotorOffset = Vector3.Zero;
94 82
95 //Angular properties 83 //Angular properties
84 private BSVMotor m_angularMotor = new BSVMotor("AngularMotor");
96 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor 85 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
97 // private int m_angularMotorApply = 0; // application frame counter 86 // private int m_angularMotorApply = 0; // application frame counter
98 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity 87 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity
99 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate 88 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
100 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate 89 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
101 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate 90 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
102 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body 91 private Vector3 m_lastAngularVelocity = Vector3.Zero;
103 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body 92 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
104 93
105 //Deflection properties 94 //Deflection properties
95 private BSVMotor m_angularDeflectionMotor = new BSVMotor("AngularDeflection");
106 private float m_angularDeflectionEfficiency = 0; 96 private float m_angularDeflectionEfficiency = 0;
107 private float m_angularDeflectionTimescale = 0; 97 private float m_angularDeflectionTimescale = 0;
108 private float m_linearDeflectionEfficiency = 0; 98 private float m_linearDeflectionEfficiency = 0;
@@ -114,33 +104,68 @@ namespace OpenSim.Region.Physics.BulletSPlugin
114 private float m_bankingTimescale = 0; 104 private float m_bankingTimescale = 0;
115 105
116 //Hover and Buoyancy properties 106 //Hover and Buoyancy properties
107 private BSVMotor m_hoverMotor = new BSVMotor("Hover");
117 private float m_VhoverHeight = 0f; 108 private float m_VhoverHeight = 0f;
118 private float m_VhoverEfficiency = 0f; 109 private float m_VhoverEfficiency = 0f;
119 private float m_VhoverTimescale = 0f; 110 private float m_VhoverTimescale = 0f;
120 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height 111 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
121 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. 112 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
122 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) 113 private float m_VehicleBuoyancy = 0f;
123 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. 114 private Vector3 m_VehicleGravity = Vector3.Zero; // Gravity computed when buoyancy set
124 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
125 115
126 //Attractor properties 116 //Attractor properties
127 private float m_verticalAttractionEfficiency = 1.0f; // damped 117 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
128 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. 118 private float m_verticalAttractionEfficiency = 1.0f; // damped
119 private float m_verticalAttractionCutoff = 500f; // per the documentation
120 // Timescale > cutoff means no vert attractor.
121 private float m_verticalAttractionTimescale = 510f;
122
123 // Just some recomputed constants:
124 static readonly float PIOverFour = ((float)Math.PI) / 4f;
125 static readonly float PIOverTwo = ((float)Math.PI) / 2f;
126
127 // For debugging, flags to turn on and off individual corrections.
128 public bool enableAngularVerticalAttraction;
129 public bool enableAngularDeflection;
130 public bool enableAngularBanking;
129 131
130 public BSDynamics(BSScene myScene, BSPrim myPrim) 132 public BSDynamics(BSScene myScene, BSPrim myPrim)
131 { 133 {
132 PhysicsScene = myScene; 134 PhysicsScene = myScene;
133 Prim = myPrim; 135 Prim = myPrim;
134 Type = Vehicle.TYPE_NONE; 136 Type = Vehicle.TYPE_NONE;
137 SetupVehicleDebugging();
138 }
139
140 // Stopgap debugging enablement. Allows source level debugging but still checking
141 // in changes by making enablement of debugging flags from INI file.
142 public void SetupVehicleDebugging()
143 {
144 enableAngularVerticalAttraction = true;
145 enableAngularDeflection = false;
146 enableAngularBanking = false;
147 if (BSParam.VehicleDebuggingEnabled != ConfigurationParameters.numericFalse)
148 {
149 enableAngularVerticalAttraction = true;
150 enableAngularDeflection = false;
151 enableAngularBanking = false;
152 }
135 } 153 }
136 154
137 // Return 'true' if this vehicle is doing vehicle things 155 // Return 'true' if this vehicle is doing vehicle things
138 public bool IsActive 156 public bool IsActive
139 { 157 {
140 get { return Type != Vehicle.TYPE_NONE; } 158 get { return (Type != Vehicle.TYPE_NONE && Prim.IsPhysicallyActive); }
141 } 159 }
142 160
143 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) 161 // Return 'true' if this a vehicle that should be sitting on the ground
162 public bool IsGroundVehicle
163 {
164 get { return (Type == Vehicle.TYPE_CAR || Type == Vehicle.TYPE_SLED); }
165 }
166
167 #region Vehicle parameter setting
168 public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
144 { 169 {
145 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); 170 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
146 switch (pParam) 171 switch (pParam)
@@ -152,13 +177,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
152 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); 177 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
153 break; 178 break;
154 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: 179 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
155 m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); 180 m_angularMotorDecayTimescale = ClampInRange(0.01f, pValue, 120);
181 m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale;
156 break; 182 break;
157 case Vehicle.ANGULAR_MOTOR_TIMESCALE: 183 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
158 m_angularMotorTimescale = Math.Max(pValue, 0.01f); 184 m_angularMotorTimescale = Math.Max(pValue, 0.01f);
185 m_angularMotor.TimeScale = m_angularMotorTimescale;
159 break; 186 break;
160 case Vehicle.BANKING_EFFICIENCY: 187 case Vehicle.BANKING_EFFICIENCY:
161 m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f)); 188 m_bankingEfficiency = ClampInRange(-1f, pValue, 1f);
162 break; 189 break;
163 case Vehicle.BANKING_MIX: 190 case Vehicle.BANKING_MIX:
164 m_bankingMix = Math.Max(pValue, 0.01f); 191 m_bankingMix = Math.Max(pValue, 0.01f);
@@ -167,10 +194,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
167 m_bankingTimescale = Math.Max(pValue, 0.01f); 194 m_bankingTimescale = Math.Max(pValue, 0.01f);
168 break; 195 break;
169 case Vehicle.BUOYANCY: 196 case Vehicle.BUOYANCY:
170 m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f)); 197 m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f);
198 m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy);
171 break; 199 break;
172 case Vehicle.HOVER_EFFICIENCY: 200 case Vehicle.HOVER_EFFICIENCY:
173 m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); 201 m_VhoverEfficiency = ClampInRange(0f, pValue, 1f);
174 break; 202 break;
175 case Vehicle.HOVER_HEIGHT: 203 case Vehicle.HOVER_HEIGHT:
176 m_VhoverHeight = pValue; 204 m_VhoverHeight = pValue;
@@ -185,33 +213,41 @@ namespace OpenSim.Region.Physics.BulletSPlugin
185 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 213 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
186 break; 214 break;
187 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: 215 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
188 m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); 216 m_linearMotorDecayTimescale = ClampInRange(0.01f, pValue, 120);
217 m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale;
189 break; 218 break;
190 case Vehicle.LINEAR_MOTOR_TIMESCALE: 219 case Vehicle.LINEAR_MOTOR_TIMESCALE:
191 m_linearMotorTimescale = Math.Max(pValue, 0.01f); 220 m_linearMotorTimescale = Math.Max(pValue, 0.01f);
221 m_linearMotor.TimeScale = m_linearMotorTimescale;
192 break; 222 break;
193 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: 223 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
194 m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); 224 m_verticalAttractionEfficiency = ClampInRange(0.1f, pValue, 1f);
225 m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency;
195 break; 226 break;
196 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: 227 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
197 m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); 228 m_verticalAttractionTimescale = Math.Max(pValue, 0.01f);
229 m_verticalAttractionMotor.TimeScale = m_verticalAttractionTimescale;
198 break; 230 break;
199 231
200 // These are vector properties but the engine lets you use a single float value to 232 // These are vector properties but the engine lets you use a single float value to
201 // set all of the components to the same value 233 // set all of the components to the same value
202 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 234 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
203 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); 235 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
236 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
204 break; 237 break;
205 case Vehicle.ANGULAR_MOTOR_DIRECTION: 238 case Vehicle.ANGULAR_MOTOR_DIRECTION:
206 m_angularMotorDirection = new Vector3(pValue, pValue, pValue); 239 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
207 // m_angularMotorApply = 100; 240 m_angularMotor.Zero();
241 m_angularMotor.SetTarget(m_angularMotorDirection);
208 break; 242 break;
209 case Vehicle.LINEAR_FRICTION_TIMESCALE: 243 case Vehicle.LINEAR_FRICTION_TIMESCALE:
210 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); 244 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
245 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
211 break; 246 break;
212 case Vehicle.LINEAR_MOTOR_DIRECTION: 247 case Vehicle.LINEAR_MOTOR_DIRECTION:
213 m_linearMotorDirection = new Vector3(pValue, pValue, pValue); 248 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
214 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); 249 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
250 m_linearMotor.SetTarget(m_linearMotorDirection);
215 break; 251 break;
216 case Vehicle.LINEAR_MOTOR_OFFSET: 252 case Vehicle.LINEAR_MOTOR_OFFSET:
217 m_linearMotorOffset = new Vector3(pValue, pValue, pValue); 253 m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
@@ -227,21 +263,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
227 { 263 {
228 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 264 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
229 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 265 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
266 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
230 break; 267 break;
231 case Vehicle.ANGULAR_MOTOR_DIRECTION: 268 case Vehicle.ANGULAR_MOTOR_DIRECTION:
232 // Limit requested angular speed to 2 rps= 4 pi rads/sec 269 // Limit requested angular speed to 2 rps= 4 pi rads/sec
233 pValue.X = Math.Max(-12.56f, Math.Min(pValue.X, 12.56f)); 270 pValue.X = ClampInRange(-12.56f, pValue.X, 12.56f);
234 pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); 271 pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f);
235 pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); 272 pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f);
236 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 273 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
237 // m_angularMotorApply = 100; 274 m_angularMotor.Zero();
275 m_angularMotor.SetTarget(m_angularMotorDirection);
238 break; 276 break;
239 case Vehicle.LINEAR_FRICTION_TIMESCALE: 277 case Vehicle.LINEAR_FRICTION_TIMESCALE:
240 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 278 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
279 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
241 break; 280 break;
242 case Vehicle.LINEAR_MOTOR_DIRECTION: 281 case Vehicle.LINEAR_MOTOR_DIRECTION:
243 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 282 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
244 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); 283 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
284 m_linearMotor.SetTarget(m_linearMotorDirection);
245 break; 285 break;
246 case Vehicle.LINEAR_MOTOR_OFFSET: 286 case Vehicle.LINEAR_MOTOR_OFFSET:
247 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); 287 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -303,7 +343,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
303 m_VhoverEfficiency = 0; 343 m_VhoverEfficiency = 0;
304 m_VhoverTimescale = 0; 344 m_VhoverTimescale = 0;
305 m_VehicleBuoyancy = 0; 345 m_VehicleBuoyancy = 0;
306 346
307 m_linearDeflectionEfficiency = 1; 347 m_linearDeflectionEfficiency = 1;
308 m_linearDeflectionTimescale = 1; 348 m_linearDeflectionTimescale = 1;
309 349
@@ -319,6 +359,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
319 359
320 m_referenceFrame = Quaternion.Identity; 360 m_referenceFrame = Quaternion.Identity;
321 m_flags = (VehicleFlag)0; 361 m_flags = (VehicleFlag)0;
362
322 break; 363 break;
323 364
324 case Vehicle.TYPE_SLED: 365 case Vehicle.TYPE_SLED:
@@ -351,10 +392,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
351 m_bankingMix = 1; 392 m_bankingMix = 1;
352 393
353 m_referenceFrame = Quaternion.Identity; 394 m_referenceFrame = Quaternion.Identity;
354 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); 395 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
355 m_flags &= 396 | VehicleFlag.HOVER_TERRAIN_ONLY
356 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 397 | VehicleFlag.HOVER_GLOBAL_HEIGHT
357 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 398 | VehicleFlag.HOVER_UP_ONLY);
399 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
400 | VehicleFlag.LIMIT_ROLL_ONLY
401 | VehicleFlag.LIMIT_MOTOR_UP);
402
358 break; 403 break;
359 case Vehicle.TYPE_CAR: 404 case Vehicle.TYPE_CAR:
360 m_linearMotorDirection = Vector3.Zero; 405 m_linearMotorDirection = Vector3.Zero;
@@ -498,6 +543,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
498 m_bankingEfficiency = 0; 543 m_bankingEfficiency = 0;
499 m_bankingMix = 0.7f; 544 m_bankingMix = 0.7f;
500 m_bankingTimescale = 5; 545 m_bankingTimescale = 5;
546
501 m_referenceFrame = Quaternion.Identity; 547 m_referenceFrame = Quaternion.Identity;
502 548
503 m_referenceFrame = Quaternion.Identity; 549 m_referenceFrame = Quaternion.Identity;
@@ -510,152 +556,467 @@ namespace OpenSim.Region.Physics.BulletSPlugin
510 | VehicleFlag.HOVER_GLOBAL_HEIGHT); 556 | VehicleFlag.HOVER_GLOBAL_HEIGHT);
511 break; 557 break;
512 } 558 }
559
560 // Update any physical parameters based on this type.
561 Refresh();
562
563 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
564 m_linearMotorDecayTimescale, m_linearFrictionTimescale,
565 1f);
566 m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
567
568 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale,
569 m_angularMotorDecayTimescale, m_angularFrictionTimescale,
570 1f);
571 m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
572
573 /* Not implemented
574 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
575 BSMotor.Infinite, BSMotor.InfiniteVector,
576 m_verticalAttractionEfficiency);
577 // Z goes away and we keep X and Y
578 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
579 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
580 */
581 }
582 #endregion // Vehicle parameter setting
583
584 public void Refresh()
585 {
586 // If asking for a refresh, reset the physical parameters before the next simulation step.
587 PhysicsScene.PostTaintObject("BSDynamics.Refresh", Prim.LocalID, delegate()
588 {
589 SetPhysicalParameters();
590 });
513 } 591 }
514 592
515 // Some of the properties of this prim may have changed. 593 // Some of the properties of this prim may have changed.
516 // Do any updating needed for a vehicle 594 // Do any updating needed for a vehicle
517 public void Refresh() 595 private void SetPhysicalParameters()
518 { 596 {
519 if (IsActive) 597 if (IsActive)
520 { 598 {
521 // Friction effects are handled by this vehicle code 599 // Remember the mass so we don't have to fetch it every step
522 BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f); 600 m_vehicleMass = Prim.Linkset.LinksetMass;
523 BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f); 601
524 602 // Friction affects are handled by this vehicle code
525 // BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, 0.8f); 603 PhysicsScene.PE.SetFriction(Prim.PhysBody, BSParam.VehicleFriction);
526 604 PhysicsScene.PE.SetRestitution(Prim.PhysBody, BSParam.VehicleRestitution);
527 VDetailLog("{0},BSDynamics.Refresh,zeroingFriction and adding damping", Prim.LocalID); 605
606 // Moderate angular movement introduced by Bullet.
607 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
608 // Maybe compute linear and angular factor and damping from params.
609 PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping);
610 PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactorV);
611 PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactorV);
612
613 // Vehicles report collision events so we know when it's on the ground
614 PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
615
616 Prim.Inertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass);
617 PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, Prim.Inertia);
618 PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody);
619
620 // Set the gravity for the vehicle depending on the buoyancy
621 // TODO: what should be done if prim and vehicle buoyancy differ?
622 m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy);
623 // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same.
624 PhysicsScene.PE.SetGravity(Prim.PhysBody, Vector3.Zero);
625
626 VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}",
627 Prim.LocalID, m_vehicleMass, Prim.Inertia, m_VehicleGravity,
628 BSParam.VehicleAngularDamping, BSParam.VehicleFriction, BSParam.VehicleRestitution,
629 BSParam.VehicleLinearFactor, BSParam.VehicleAngularFactor
630 );
631 }
632 else
633 {
634 if (Prim.PhysBody.HasPhysicalBody)
635 PhysicsScene.PE.RemoveFromCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
528 } 636 }
529 } 637 }
530 638
531 public bool RemoveBodyDependencies(BSPhysObject prim) 639 public bool RemoveBodyDependencies(BSPhysObject prim)
532 { 640 {
533 // If active, we need to add our properties back when the body is rebuilt. 641 Refresh();
534 return IsActive; 642 return IsActive;
535 } 643 }
536 644
537 public void RestoreBodyDependencies(BSPhysObject prim) 645 #region Known vehicle value functions
646 // Vehicle physical parameters that we buffer from constant getting and setting.
647 // The "m_known*" values are unknown until they are fetched and the m_knownHas flag is set.
648 // Changing is remembered and the parameter is stored back into the physics engine only if updated.
649 // This does two things: 1) saves continuious calls into unmanaged code, and
650 // 2) signals when a physics property update must happen back to the simulator
651 // to update values modified for the vehicle.
652 private int m_knownChanged;
653 private int m_knownHas;
654 private float m_knownTerrainHeight;
655 private float m_knownWaterLevel;
656 private Vector3 m_knownPosition;
657 private Vector3 m_knownVelocity;
658 private Vector3 m_knownForce;
659 private Vector3 m_knownForceImpulse;
660 private Quaternion m_knownOrientation;
661 private Vector3 m_knownRotationalVelocity;
662 private Vector3 m_knownRotationalForce;
663 private Vector3 m_knownRotationalImpulse;
664 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
665
666 private const int m_knownChangedPosition = 1 << 0;
667 private const int m_knownChangedVelocity = 1 << 1;
668 private const int m_knownChangedForce = 1 << 2;
669 private const int m_knownChangedForceImpulse = 1 << 3;
670 private const int m_knownChangedOrientation = 1 << 4;
671 private const int m_knownChangedRotationalVelocity = 1 << 5;
672 private const int m_knownChangedRotationalForce = 1 << 6;
673 private const int m_knownChangedRotationalImpulse = 1 << 7;
674 private const int m_knownChangedTerrainHeight = 1 << 8;
675 private const int m_knownChangedWaterLevel = 1 << 9;
676 private const int m_knownChangedForwardVelocity = 1 <<10;
677
678 public void ForgetKnownVehicleProperties()
679 {
680 m_knownHas = 0;
681 m_knownChanged = 0;
682 }
683 // Push all the changed values back into the physics engine
684 public void PushKnownChanged()
685 {
686 if (m_knownChanged != 0)
687 {
688 if ((m_knownChanged & m_knownChangedPosition) != 0)
689 Prim.ForcePosition = m_knownPosition;
690
691 if ((m_knownChanged & m_knownChangedOrientation) != 0)
692 Prim.ForceOrientation = m_knownOrientation;
693
694 if ((m_knownChanged & m_knownChangedVelocity) != 0)
695 {
696 Prim.ForceVelocity = m_knownVelocity;
697 // Fake out Bullet by making it think the velocity is the same as last time.
698 // Bullet does a bunch of smoothing for changing parameters.
699 // Since the vehicle is demanding this setting, we override Bullet's smoothing
700 // by telling Bullet the value was the same last time.
701 // PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, m_knownVelocity);
702 }
703
704 if ((m_knownChanged & m_knownChangedForce) != 0)
705 Prim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/);
706
707 if ((m_knownChanged & m_knownChangedForceImpulse) != 0)
708 Prim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/);
709
710 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
711 {
712 Prim.ForceRotationalVelocity = m_knownRotationalVelocity;
713 // PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity);
714 }
715
716 if ((m_knownChanged & m_knownChangedRotationalImpulse) != 0)
717 Prim.ApplyTorqueImpulse((Vector3)m_knownRotationalImpulse, true /*inTaintTime*/);
718
719 if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
720 {
721 Prim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/);
722 }
723
724 // If we set one of the values (ie, the physics engine didn't do it) we must force
725 // an UpdateProperties event to send the changes up to the simulator.
726 PhysicsScene.PE.PushUpdate(Prim.PhysBody);
727 }
728 m_knownChanged = 0;
729 }
730
731 // Since the computation of terrain height can be a little involved, this routine
732 // is used to fetch the height only once for each vehicle simulation step.
733 Vector3 lastRememberedHeightPos;
734 private float GetTerrainHeight(Vector3 pos)
538 { 735 {
539 if (Prim.LocalID != prim.LocalID) 736 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos)
540 { 737 {
541 // The call should be on us by our prim. Error if not. 738 lastRememberedHeightPos = pos;
542 PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}", 739 m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
543 LogHeader, prim.LocalID, Prim.LocalID); 740 m_knownHas |= m_knownChangedTerrainHeight;
544 return; 741 }
742 return m_knownTerrainHeight;
743 }
744
745 // Since the computation of water level can be a little involved, this routine
746 // is used ot fetch the level only once for each vehicle simulation step.
747 private float GetWaterLevel(Vector3 pos)
748 {
749 if ((m_knownHas & m_knownChangedWaterLevel) == 0)
750 {
751 m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos);
752 m_knownHas |= m_knownChangedWaterLevel;
753 }
754 return (float)m_knownWaterLevel;
755 }
756
757 private Vector3 VehiclePosition
758 {
759 get
760 {
761 if ((m_knownHas & m_knownChangedPosition) == 0)
762 {
763 m_knownPosition = Prim.ForcePosition;
764 m_knownHas |= m_knownChangedPosition;
765 }
766 return m_knownPosition;
767 }
768 set
769 {
770 m_knownPosition = value;
771 m_knownChanged |= m_knownChangedPosition;
772 m_knownHas |= m_knownChangedPosition;
545 } 773 }
546 Refresh();
547 } 774 }
548 775
776 private Quaternion VehicleOrientation
777 {
778 get
779 {
780 if ((m_knownHas & m_knownChangedOrientation) == 0)
781 {
782 m_knownOrientation = Prim.ForceOrientation;
783 m_knownHas |= m_knownChangedOrientation;
784 }
785 return m_knownOrientation;
786 }
787 set
788 {
789 m_knownOrientation = value;
790 m_knownChanged |= m_knownChangedOrientation;
791 m_knownHas |= m_knownChangedOrientation;
792 }
793 }
794
795 private Vector3 VehicleVelocity
796 {
797 get
798 {
799 if ((m_knownHas & m_knownChangedVelocity) == 0)
800 {
801 m_knownVelocity = Prim.ForceVelocity;
802 m_knownHas |= m_knownChangedVelocity;
803 }
804 return m_knownVelocity;
805 }
806 set
807 {
808 m_knownVelocity = value;
809 m_knownChanged |= m_knownChangedVelocity;
810 m_knownHas |= m_knownChangedVelocity;
811 }
812 }
813
814 private void VehicleAddForce(Vector3 pForce)
815 {
816 if ((m_knownHas & m_knownChangedForce) == 0)
817 {
818 m_knownForce = Vector3.Zero;
819 m_knownHas |= m_knownChangedForce;
820 }
821 m_knownForce += pForce;
822 m_knownChanged |= m_knownChangedForce;
823 }
824
825 private void VehicleAddForceImpulse(Vector3 pImpulse)
826 {
827 if ((m_knownHas & m_knownChangedForceImpulse) == 0)
828 {
829 m_knownForceImpulse = Vector3.Zero;
830 m_knownHas |= m_knownChangedForceImpulse;
831 }
832 m_knownForceImpulse += pImpulse;
833 m_knownChanged |= m_knownChangedForceImpulse;
834 }
835
836 private Vector3 VehicleRotationalVelocity
837 {
838 get
839 {
840 if ((m_knownHas & m_knownChangedRotationalVelocity) == 0)
841 {
842 m_knownRotationalVelocity = Prim.ForceRotationalVelocity;
843 m_knownHas |= m_knownChangedRotationalVelocity;
844 }
845 return (Vector3)m_knownRotationalVelocity;
846 }
847 set
848 {
849 m_knownRotationalVelocity = value;
850 m_knownChanged |= m_knownChangedRotationalVelocity;
851 m_knownHas |= m_knownChangedRotationalVelocity;
852 }
853 }
854 private void VehicleAddAngularForce(Vector3 aForce)
855 {
856 if ((m_knownHas & m_knownChangedRotationalForce) == 0)
857 {
858 m_knownRotationalForce = Vector3.Zero;
859 }
860 m_knownRotationalForce += aForce;
861 m_knownChanged |= m_knownChangedRotationalForce;
862 m_knownHas |= m_knownChangedRotationalForce;
863 }
864 private void VehicleAddRotationalImpulse(Vector3 pImpulse)
865 {
866 if ((m_knownHas & m_knownChangedRotationalImpulse) == 0)
867 {
868 m_knownRotationalImpulse = Vector3.Zero;
869 m_knownHas |= m_knownChangedRotationalImpulse;
870 }
871 m_knownRotationalImpulse += pImpulse;
872 m_knownChanged |= m_knownChangedRotationalImpulse;
873 }
874
875 // Vehicle relative forward velocity
876 private Vector3 VehicleForwardVelocity
877 {
878 get
879 {
880 if ((m_knownHas & m_knownChangedForwardVelocity) == 0)
881 {
882 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
883 m_knownHas |= m_knownChangedForwardVelocity;
884 }
885 return m_knownForwardVelocity;
886 }
887 }
888 private float VehicleForwardSpeed
889 {
890 get
891 {
892 return VehicleForwardVelocity.X;
893 }
894 }
895
896 #endregion // Known vehicle value functions
897
549 // One step of the vehicle properties for the next 'pTimestep' seconds. 898 // One step of the vehicle properties for the next 'pTimestep' seconds.
550 internal void Step(float pTimestep) 899 internal void Step(float pTimestep)
551 { 900 {
552 if (!IsActive) return; 901 if (!IsActive) return;
553 902
554 // DEBUG 903 ForgetKnownVehicleProperties();
555 // Because Bullet does apply forces to the vehicle, our last computed
556 // linear and angular velocities are not what is happening now.
557 // Vector3 externalAngularVelocity = Prim.ForceRotationalVelocity - m_lastAngularVelocity;
558 // m_lastAngularVelocity += (externalAngularVelocity * 0.5f) * pTimestep;
559 // m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time
560 // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG:
561 // END DEBUG
562
563 m_vehicleMass = Prim.Linkset.LinksetMass;
564 904
565 MoveLinear(pTimestep); 905 MoveLinear(pTimestep);
566 // Commented out for debug
567 MoveAngular(pTimestep); 906 MoveAngular(pTimestep);
568 // Prim.ApplyTorqueImpulse(-Prim.RotationalVelocity * m_vehicleMass, false); // DEBUG DEBUG
569 // Prim.ForceRotationalVelocity = -Prim.RotationalVelocity; // DEBUG DEBUG
570 907
571 LimitRotation(pTimestep); 908 LimitRotation(pTimestep);
572 909
573 // remember the position so next step we can limit absolute movement effects 910 // remember the position so next step we can limit absolute movement effects
574 m_lastPositionVector = Prim.ForcePosition; 911 m_lastPositionVector = VehiclePosition;
575 912
576 VDetailLog("{0},BSDynamics.Step,frict={1},grav={2},inertia={3},mass={4}", // DEBUG DEBUG 913 // If we forced the changing of some vehicle parameters, update the values and
577 Prim.LocalID, 914 // for the physics engine to note the changes so an UpdateProperties event will happen.
578 BulletSimAPI.GetFriction2(Prim.PhysBody.ptr), 915 PushKnownChanged();
579 BulletSimAPI.GetGravity2(Prim.PhysBody.ptr), 916
580 Prim.Inertia, 917 if (PhysicsScene.VehiclePhysicalLoggingEnabled)
581 m_vehicleMass 918 PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
582 ); 919
583 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 920 VDetailLog("{0},BSDynamics.Step,done,pos={1}, force={2},velocity={3},angvel={4}",
584 Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); 921 Prim.LocalID, VehiclePosition, m_knownForce, VehicleVelocity, VehicleRotationalVelocity);
585 }// end Step 922 }
586 923
587 // Apply the effect of the linear motor. 924 // Called after the simulation step
588 // Also does hover and float. 925 internal void PostStep(float pTimestep)
926 {
927 if (!IsActive) return;
928
929 if (PhysicsScene.VehiclePhysicalLoggingEnabled)
930 PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
931 }
932
933 // Apply the effect of the linear motor and other linear motions (like hover and float).
589 private void MoveLinear(float pTimestep) 934 private void MoveLinear(float pTimestep)
590 { 935 {
591 // m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates 936 ComputeLinearVelocity(pTimestep);
592 // m_lastLinearVelocityVector is the current speed we are moving in that direction
593 if (m_linearMotorDirection.LengthSquared() > 0.001f)
594 {
595 Vector3 origDir = m_linearMotorDirection; // DEBUG
596 Vector3 origVel = m_lastLinearVelocityVector; // DEBUG
597 // DEBUG: the vehicle velocity rotated to be relative to vehicle coordinates for comparison
598 Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG
599 937
600 // Add (desiredVelocity - lastAppliedVelocity) / howLongItShouldTakeToComplete 938 ComputeLinearTerrainHeightCorrection(pTimestep);
601 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep;
602 m_lastLinearVelocityVector += addAmount;
603 939
604 float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; 940 ComputeLinearHover(pTimestep);
605 m_linearMotorDirection *= (1f - decayFactor);
606 941
607 // Rotate new object velocity from vehicle relative to world coordinates 942 ComputeLinearBlockingEndPoint(pTimestep);
608 m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation;
609 943
610 // Apply friction for next time 944 ComputeLinearMotorUp(pTimestep);
611 Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep;
612 m_lastLinearVelocityVector *= (Vector3.One - frictionFactor);
613 945
614 VDetailLog("{0},MoveLinear,nonZero,origlmDir={1},origlvVel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lvVec={8},newVel={9}", 946 ApplyGravity(pTimestep);
615 Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, 947
616 m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); 948 // If not changing some axis, reduce out velocity
617 } 949 if ((m_flags & (VehicleFlag.NO_X | VehicleFlag.NO_Y | VehicleFlag.NO_Z)) != 0)
618 else
619 { 950 {
620 // if what remains of direction is very small, zero it. 951 Vector3 vel = VehicleVelocity;
621 m_linearMotorDirection = Vector3.Zero; 952 if ((m_flags & (VehicleFlag.NO_X)) != 0)
622 m_lastLinearVelocityVector = Vector3.Zero; 953 vel.X = 0;
623 m_newVelocity = Vector3.Zero; 954 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
955 vel.Y = 0;
956 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
957 vel.Z = 0;
958 VehicleVelocity = vel;
959 }
624 960
625 VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); 961 // ==================================================================
962 // Clamp high or low velocities
963 float newVelocityLengthSq = VehicleVelocity.LengthSquared();
964 if (newVelocityLengthSq > BSParam.VehicleMaxLinearVelocitySq)
965 {
966 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG
967 VehicleVelocity /= VehicleVelocity.Length();
968 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity;
969 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}",
970 Prim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySq, VehicleVelocity);
626 } 971 }
972 else if (newVelocityLengthSq < 0.001f)
973 VehicleVelocity = Vector3.Zero;
627 974
628 // m_newVelocity is velocity computed from linear motor in world coordinates 975 VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", Prim.LocalID, Prim.IsColliding, VehicleVelocity );
629 976
630 // Gravity and Buoyancy 977 } // end MoveLinear()
631 // There is some gravity, make a gravity force vector that is applied after object velocity.
632 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
633 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy);
634 978
635 /* 979 public void ComputeLinearVelocity(float pTimestep)
636 * RA: Not sure why one would do this unless we are hoping external forces are doing gravity, ... 980 {
637 // Preserve the current Z velocity 981 // Step the motor from the current value. Get the correction needed this step.
638 Vector3 vel_now = m_prim.Velocity; 982 Vector3 origVelW = VehicleVelocity; // DEBUG
639 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity 983 Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation);
640 */ 984 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
985
986 // Motor is vehicle coordinates. Rotate it to world coordinates
987 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
988
989 // If we're a ground vehicle, don't add any upward Z movement
990 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
991 {
992 if (linearMotorVelocityW.Z > 0f)
993 linearMotorVelocityW.Z = 0f;
994 }
995
996 // Add this correction to the velocity to make it faster/slower.
997 VehicleVelocity += linearMotorVelocityW;
641 998
642 Vector3 pos = Prim.ForcePosition; 999 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5}",
643// 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); 1000 Prim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, linearMotorVelocityW, VehicleVelocity);
1001 }
644 1002
1003 public void ComputeLinearTerrainHeightCorrection(float pTimestep)
1004 {
645 // If below the terrain, move us above the ground a little. 1005 // If below the terrain, move us above the ground a little.
646 float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 1006 // TODO: Consider taking the rotated size of the object or possibly casting a ray.
647 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. 1007 if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition))
648 // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
649 // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
650 // if (rotatedSize.Z < terrainHeight)
651 if (pos.Z < terrainHeight)
652 { 1008 {
653 pos.Z = terrainHeight + 2; 1009 // Force position because applying force won't get the vehicle through the terrain
654 Prim.ForcePosition = pos; 1010 Vector3 newPosition = VehiclePosition;
655 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); 1011 newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f;
1012 VehiclePosition = newPosition;
1013 VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}",
1014 Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition);
656 } 1015 }
1016 }
657 1017
658 // Check if hovering 1018 public void ComputeLinearHover(float pTimestep)
1019 {
659 // m_VhoverEfficiency: 0=bouncy, 1=totally damped 1020 // m_VhoverEfficiency: 0=bouncy, 1=totally damped
660 // m_VhoverTimescale: time to achieve height 1021 // m_VhoverTimescale: time to achieve height
661 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) 1022 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
@@ -663,11 +1024,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
663 // We should hover, get the target height 1024 // We should hover, get the target height
664 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) 1025 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
665 { 1026 {
666 m_VhoverTargetHeight = Prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; 1027 m_VhoverTargetHeight = GetWaterLevel(VehiclePosition) + m_VhoverHeight;
667 } 1028 }
668 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 1029 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
669 { 1030 {
670 m_VhoverTargetHeight = terrainHeight + m_VhoverHeight; 1031 m_VhoverTargetHeight = GetTerrainHeight(VehiclePosition) + m_VhoverHeight;
671 } 1032 }
672 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 1033 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
673 { 1034 {
@@ -677,45 +1038,63 @@ namespace OpenSim.Region.Physics.BulletSPlugin
677 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) 1038 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
678 { 1039 {
679 // If body is already heigher, use its height as target height 1040 // If body is already heigher, use its height as target height
680 if (pos.Z > m_VhoverTargetHeight) 1041 if (VehiclePosition.Z > m_VhoverTargetHeight)
681 m_VhoverTargetHeight = pos.Z; 1042 m_VhoverTargetHeight = VehiclePosition.Z;
682 } 1043 }
1044
683 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 1045 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
684 { 1046 {
685 if (Math.Abs(pos.Z - m_VhoverTargetHeight) > 0.2f) 1047 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
686 { 1048 {
1049 Vector3 pos = VehiclePosition;
687 pos.Z = m_VhoverTargetHeight; 1050 pos.Z = m_VhoverTargetHeight;
688 Prim.ForcePosition = pos; 1051 VehiclePosition = pos;
1052
1053 VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", Prim.LocalID, pos);
689 } 1054 }
690 } 1055 }
691 else 1056 else
692 { 1057 {
693 float verticalError = pos.Z - m_VhoverTargetHeight; 1058 // Error is positive if below the target and negative if above.
694 // RA: where does the 50 come from? 1059 Vector3 hpos = VehiclePosition;
695 float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); 1060 float verticalError = m_VhoverTargetHeight - hpos.Z;
696 // Replace Vertical speed with correction figure if significant 1061 float verticalCorrection = verticalError / m_VhoverTimescale;
697 if (Math.Abs(verticalError) > 0.01f) 1062 verticalCorrection *= m_VhoverEfficiency;
698 { 1063
699 m_newVelocity.Z += verticalCorrectionVelocity; 1064 hpos.Z += verticalCorrection;
700 //KF: m_VhoverEfficiency is not yet implemented 1065 VehiclePosition = hpos;
701 } 1066
702 else if (verticalError < -0.01) 1067 // Since we are hovering, we need to do the opposite of falling -- get rid of world Z
703 { 1068 Vector3 vel = VehicleVelocity;
704 m_newVelocity.Z -= verticalCorrectionVelocity; 1069 vel.Z = 0f;
705 } 1070 VehicleVelocity = vel;
706 else 1071
707 { 1072 /*
708 m_newVelocity.Z = 0f; 1073 float verticalCorrectionVelocity = verticalError / m_VhoverTimescale;
709 } 1074 Vector3 verticalCorrection = new Vector3(0f, 0f, verticalCorrectionVelocity);
1075 verticalCorrection *= m_vehicleMass;
1076
1077 // TODO: implement m_VhoverEfficiency correctly
1078 VehicleAddForceImpulse(verticalCorrection);
1079 */
1080
1081 VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corr={7}",
1082 Prim.LocalID, VehiclePosition, m_VhoverEfficiency,
1083 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
1084 verticalError, verticalCorrection);
710 } 1085 }
711 1086
712 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", Prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight);
713 } 1087 }
1088 }
714 1089
1090 public bool ComputeLinearBlockingEndPoint(float pTimestep)
1091 {
1092 bool changed = false;
1093
1094 Vector3 pos = VehiclePosition;
715 Vector3 posChange = pos - m_lastPositionVector; 1095 Vector3 posChange = pos - m_lastPositionVector;
716 if (m_BlockingEndPoint != Vector3.Zero) 1096 if (m_BlockingEndPoint != Vector3.Zero)
717 { 1097 {
718 bool changed = false;
719 if (pos.X >= (m_BlockingEndPoint.X - (float)1)) 1098 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
720 { 1099 {
721 pos.X -= posChange.X + 1; 1100 pos.X -= posChange.X + 1;
@@ -743,233 +1122,118 @@ namespace OpenSim.Region.Physics.BulletSPlugin
743 } 1122 }
744 if (changed) 1123 if (changed)
745 { 1124 {
746 Prim.ForcePosition = pos; 1125 VehiclePosition = pos;
747 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", 1126 VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
748 Prim.LocalID, m_BlockingEndPoint, posChange, pos); 1127 Prim.LocalID, m_BlockingEndPoint, posChange, pos);
749 } 1128 }
750 } 1129 }
1130 return changed;
1131 }
751 1132
752 #region downForce 1133 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
753 Vector3 downForce = Vector3.Zero; 1134 // Prevent ground vehicles from motoring into the sky. This flag has a subtle effect when
754 1135 // used with conjunction with banking: the strength of the banking will decay when the
1136 // vehicle no longer experiences collisions. The decay timescale is the same as
1137 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
1138 // when they are in mid jump.
1139 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
1140 // This is just using the ground and a general collision check. Should really be using
1141 // a downward raycast to find what is below.
1142 public void ComputeLinearMotorUp(float pTimestep)
1143 {
755 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 1144 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
756 { 1145 {
757 // If the vehicle is motoring into the sky, get it going back down. 1146 // This code tries to decide if the object is not on the ground and then pushing down
758 // Is this an angular force or both linear and angular?? 1147 /*
759 float distanceAboveGround = pos.Z - terrainHeight; 1148 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
760 if (distanceAboveGround > 2f) 1149 distanceAboveGround = VehiclePosition.Z - targetHeight;
1150 // Not colliding if the vehicle is off the ground
1151 if (!Prim.IsColliding)
761 { 1152 {
762 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
763 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1153 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
764 downForce = new Vector3(0, 0, -distanceAboveGround); 1154 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround);
765 } 1155 }
766 // TODO: this calculation is all wrong. From the description at 1156 // TODO: this calculation is wrong. From the description at
767 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce 1157 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
768 // has a decay factor. This says this force should 1158 // has a decay factor. This says this force should
769 // be computed with a motor. 1159 // be computed with a motor.
770 VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}", 1160 // TODO: add interaction with banking.
771 Prim.LocalID, distanceAboveGround, downForce); 1161 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
772 } 1162 Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret);
773 #endregion // downForce 1163 */
774 1164
775 // If not changing some axis, reduce out velocity 1165 // Another approach is to measure if we're going up. If going up and not colliding,
776 if ((m_flags & (VehicleFlag.NO_X)) != 0) 1166 // the vehicle is in the air. Fix that by pushing down.
777 m_newVelocity.X = 0; 1167 if (!Prim.IsColliding && VehicleVelocity.Z > 0.1)
778 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 1168 {
779 m_newVelocity.Y = 0; 1169 // Get rid of any of the velocity vector that is pushing us up.
780 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 1170 float upVelocity = VehicleVelocity.Z;
781 m_newVelocity.Z = 0; 1171 VehicleVelocity += new Vector3(0, 0, -upVelocity);
782 1172
783 // Clamp REALLY high or low velocities 1173 /*
784 if (m_newVelocity.LengthSquared() > 1e6f) 1174 // If we're pointed up into the air, we should nose down
785 { 1175 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
786 m_newVelocity /= m_newVelocity.Length(); 1176 // The rotation around the Y axis is pitch up or down
787 m_newVelocity *= 1000f; 1177 if (pointingDirection.Y > 0.01f)
1178 {
1179 float angularCorrectionForce = -(float)Math.Asin(pointingDirection.Y);
1180 Vector3 angularCorrectionVector = new Vector3(0f, angularCorrectionForce, 0f);
1181 // Rotate into world coordinates and apply to vehicle
1182 angularCorrectionVector *= VehicleOrientation;
1183 VehicleAddAngularForce(angularCorrectionVector);
1184 VDetailLog("{0}, MoveLinear,limitMotorUp,newVel={1},pntDir={2},corrFrc={3},aCorr={4}",
1185 Prim.LocalID, VehicleVelocity, pointingDirection, angularCorrectionForce, angularCorrectionVector);
1186 }
1187 */
1188 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}",
1189 Prim.LocalID, Prim.IsColliding, upVelocity, VehicleVelocity);
1190 }
788 } 1191 }
789 else if (m_newVelocity.LengthSquared() < 1e-6f) 1192 }
790 m_newVelocity = Vector3.Zero;
791 1193
792 // Stuff new linear velocity into the vehicle 1194 private void ApplyGravity(float pTimeStep)
793 Prim.ForceVelocity = m_newVelocity; 1195 {
794 // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG 1196 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass;
795 1197
796 Vector3 totalDownForce = downForce + grav; 1198 // Hack to reduce downward force if the vehicle is probably sitting on the ground
797 if (totalDownForce != Vector3.Zero) 1199 if (Prim.IsColliding && IsGroundVehicle)
798 { 1200 appliedGravity *= BSParam.VehicleGroundGravityFudge;
799 Prim.AddForce(totalDownForce * m_vehicleMass, false);
800 // Prim.ApplyForceImpulse(totalDownForce * m_vehicleMass, false);
801 }
802 1201
803 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}", 1202 VehicleAddForce(appliedGravity);
804 Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, Prim.Velocity, totalDownForce);
805 1203
806 } // end MoveLinear() 1204 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},appliedForce={3}",
1205 Prim.LocalID, m_VehicleGravity, Prim.IsColliding, appliedGravity);
1206 }
807 1207
808 // ======================================================================= 1208 // =======================================================================
1209 // =======================================================================
809 // Apply the effect of the angular motor. 1210 // Apply the effect of the angular motor.
1211 // The 'contribution' is how much angular correction velocity each function wants.
1212 // All the contributions are added together and the resulting velocity is
1213 // set directly on the vehicle.
810 private void MoveAngular(float pTimestep) 1214 private void MoveAngular(float pTimestep)
811 { 1215 {
812 // m_angularMotorDirection // angular velocity requested by LSL motor 1216 ComputeAngularTurning(pTimestep);
813 // m_angularMotorApply // application frame counter
814 // m_angularMotorVelocity // current angular motor velocity (ramps up and down)
815 // m_angularMotorTimescale // motor angular velocity ramp up rate
816 // m_angularMotorDecayTimescale // motor angular velocity decay rate
817 // m_angularFrictionTimescale // body angular velocity decay rate
818 // m_lastAngularVelocity // what was last applied to body
819
820 if (m_angularMotorDirection.LengthSquared() > 0.0001)
821 {
822 Vector3 origVel = m_angularMotorVelocity;
823 Vector3 origDir = m_angularMotorDirection;
824
825 // new velocity += error / ( time to get there / step interval)
826 // requested direction - current vehicle direction
827 m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep);
828 // decay requested direction
829 m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale));
830
831 VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}",
832 Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity);
833 }
834 else
835 {
836 m_angularMotorVelocity = Vector3.Zero;
837 }
838
839 #region Vertical attactor
840 1217
841 Vector3 vertattr = Vector3.Zero; 1218 ComputeAngularVerticalAttraction();
842 Vector3 deflection = Vector3.Zero;
843 Vector3 banking = Vector3.Zero;
844 1219
845 // If vertical attaction timescale is reasonable and we applied an angular force last time... 1220 ComputeAngularDeflection();
846 if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero)
847 {
848 float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale;
849 if (Prim.IsColliding)
850 VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale);
851
852 VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
853
854 // Create a vector of the vehicle "up" in world coordinates
855 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation;
856 // verticalError.X and .Y are the World error amounts. They are 0 when there is no
857 // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its
858 // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall
859 // and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be
860 // modulated to prevent a stable inverted body.
861
862 // Error is 0 (no error) to +/- 2 (max error)
863 if (verticalError.Z < 0.0f)
864 {
865 verticalError.X = 2.0f - verticalError.X;
866 verticalError.Y = 2.0f - verticalError.Y;
867 }
868 // scale it by VAservo (timestep and timescale)
869 verticalError = verticalError * VAservo;
870
871 // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y
872 // then .X increases, so change Body angular velocity X based on Y, and Y based on X.
873 // Z is not changed.
874 vertattr.X = verticalError.Y;
875 vertattr.Y = - verticalError.X;
876 vertattr.Z = 0f;
877
878 // scaling appears better usingsquare-law
879 Vector3 angularVelocity = Prim.ForceRotationalVelocity;
880 float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
881 vertattr.X += bounce * angularVelocity.X;
882 vertattr.Y += bounce * angularVelocity.Y;
883 1221
884 VDetailLog("{0},MoveAngular,verticalAttraction,VAservo={1},effic={2},verticalError={3},bounce={4},vertattr={5}", 1222 ComputeAngularBanking();
885 Prim.LocalID, VAservo, m_verticalAttractionEfficiency, verticalError, bounce, vertattr);
886 1223
887 } 1224 // ==================================================================
888 #endregion // Vertical attactor 1225 if (VehicleRotationalVelocity.ApproxEquals(Vector3.Zero, 0.0001f))
889
890 #region Deflection
891
892 if (m_angularDeflectionEfficiency != 0)
893 { 1226 {
894 // Compute a scaled vector that points in the preferred axis (X direction) 1227 // The vehicle is not adding anything angular wise.
895 Vector3 scaledDefaultDirection = 1228 VehicleRotationalVelocity = Vector3.Zero;
896 new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); 1229 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID);
897 // Adding the current vehicle orientation and reference frame displaces the orientation to the frame.
898 // Rotate the scaled default axix relative to the actual vehicle direction giving where it should point.
899 Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame);
900
901 // Scale by efficiency and timescale
902 deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep;
903
904 VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}",
905 Prim.LocalID, preferredAxisOfMotion, deflection);
906 // This deflection computation is not correct.
907 deflection = Vector3.Zero;
908 } 1230 }
909 1231 else
910 #endregion
911
912 #region Banking
913
914 if (m_bankingEfficiency != 0)
915 { 1232 {
916 Vector3 dir = Vector3.One * Prim.ForceOrientation; 1233 VDetailLog("{0}, MoveAngular,done,nonZero,angVel={1}", Prim.LocalID, VehicleRotationalVelocity);
917 float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1);
918 //Changes which way it banks in and out of turns
919
920 //Use the square of the efficiency, as it looks much more how SL banking works
921 float effSquared = (m_bankingEfficiency*m_bankingEfficiency);
922 if (m_bankingEfficiency < 0)
923 effSquared *= -1; //Keep the negative!
924
925 float mix = Math.Abs(m_bankingMix);
926 if (m_angularMotorVelocity.X == 0)
927 {
928 /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f))
929 {
930 Vector3 axisAngle;
931 float angle;
932 parent.Orientation.GetAxisAngle(out axisAngle, out angle);
933 Vector3 rotatedVel = parent.Velocity * parent.Orientation;
934 if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0))
935 m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10;
936 else
937 m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10;
938 }*/
939 }
940 else
941 banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4;
942 if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix)
943 //If they are colliding, we probably shouldn't shove the prim around... probably
944 {
945 float angVelZ = m_angularMotorVelocity.X*-1;
946 /*if(angVelZ > mix)
947 angVelZ = mix;
948 else if(angVelZ < -mix)
949 angVelZ = -mix;*/
950 //This controls how fast and how far the banking occurs
951 Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0);
952 if (bankingRot.X > 3)
953 bankingRot.X = 3;
954 else if (bankingRot.X < -3)
955 bankingRot.X = -3;
956 bankingRot *= Prim.ForceOrientation;
957 banking += bankingRot;
958 }
959 m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency;
960 VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},banking={3}",
961 Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, banking);
962 } 1234 }
963 1235
964 #endregion 1236 // ==================================================================
965
966 m_lastVertAttractor = vertattr;
967
968 // Sum velocities
969 m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection;
970
971 #region Linear Motor Offset
972
973 //Offset section 1237 //Offset section
974 if (m_linearMotorOffset != Vector3.Zero) 1238 if (m_linearMotorOffset != Vector3.Zero)
975 { 1239 {
@@ -985,8 +1249,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
985 // 1249 //
986 // The torque created is the linear velocity crossed with the offset 1250 // The torque created is the linear velocity crossed with the offset
987 1251
988 // NOTE: this computation does should be in the linear section 1252 // TODO: this computation should be in the linear section
989 // because there we know the impulse being applied. 1253 // because that is where we know the impulse being applied.
990 Vector3 torqueFromOffset = Vector3.Zero; 1254 Vector3 torqueFromOffset = Vector3.Zero;
991 // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse); 1255 // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse);
992 if (float.IsNaN(torqueFromOffset.X)) 1256 if (float.IsNaN(torqueFromOffset.X))
@@ -995,47 +1259,215 @@ namespace OpenSim.Region.Physics.BulletSPlugin
995 torqueFromOffset.Y = 0; 1259 torqueFromOffset.Y = 0;
996 if (float.IsNaN(torqueFromOffset.Z)) 1260 if (float.IsNaN(torqueFromOffset.Z))
997 torqueFromOffset.Z = 0; 1261 torqueFromOffset.Z = 0;
998 torqueFromOffset *= m_vehicleMass; 1262
999 Prim.ApplyTorqueImpulse(torqueFromOffset, true); 1263 VehicleAddAngularForce(torqueFromOffset * m_vehicleMass);
1000 VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); 1264 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
1001 } 1265 }
1002 1266
1003 #endregion 1267 }
1004 1268
1269 private void ComputeAngularTurning(float pTimestep)
1270 {
1271 // The user wants this many radians per second angular change?
1272 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation);
1273 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV);
1274
1275 // ==================================================================
1276 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1277 // This flag prevents linear deflection parallel to world z-axis. This is useful
1278 // for preventing ground vehicles with large linear deflection, like bumper cars,
1279 // from climbing their linear deflection into the sky.
1280 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
1281 // TODO: This is here because this is where ODE put it but documentation says it
1282 // is a linear effect. Where should this check go?
1005 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 1283 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1006 { 1284 {
1007 m_lastAngularVelocity.X = 0; 1285 angularMotorContributionV.X = 0f;
1008 m_lastAngularVelocity.Y = 0; 1286 angularMotorContributionV.Y = 0f;
1009 VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
1010 } 1287 }
1011 1288
1012 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) 1289 VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation;
1290 VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContributionV);
1291 }
1292
1293 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1294 // Some vehicles, like boats, should always keep their up-side up. This can be done by
1295 // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to
1296 // the world z-axis (a.k.a. "up"). To take advantage of this feature you would set the
1297 // VEHICLE_VERTICAL_ATTRACTION_TIMESCALE to control the period of the spring frequency,
1298 // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An
1299 // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an
1300 // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay.
1301 public void ComputeAngularVerticalAttraction()
1302 {
1303 // If vertical attaction timescale is reasonable
1304 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1013 { 1305 {
1014 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. 1306 Vector3 vertContributionV = Vector3.Zero;
1015 Prim.ZeroAngularMotion(true); 1307 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1016 VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); 1308
1309 // Take a vector pointing up and convert it from world to vehicle relative coords.
1310 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
1311
1312 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1313 // is now:
1314 // leaning to one side: rotated around the X axis with the Y value going
1315 // from zero (nearly straight up) to one (completely to the side)) or
1316 // leaning front-to-back: rotated around the Y axis with the value of X being between
1317 // zero and one.
1318 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1319
1320 // Y error means needed rotation around X axis and visa versa.
1321 // Since the error goes from zero to one, the asin is the corresponding angle.
1322 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1323 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1324 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1325
1326 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1327 if (verticalError.Z < 0f)
1328 {
1329 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour;
1330 // vertContribution.Y -= PIOverFour;
1331 }
1332
1333 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1334 // Correction happens over a number of seconds.
1335 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1336 vertContributionV /= m_verticalAttractionTimescale;
1337
1338 VehicleRotationalVelocity += vertContributionV * VehicleOrientation;
1339
1340 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
1341 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
1342 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
1017 } 1343 }
1018 else 1344 }
1345
1346 // Angular correction to correct the direction the vehicle is pointing to be
1347 // the direction is should want to be pointing.
1348 // The vehicle is moving in some direction and correct its orientation to it is pointing
1349 // in that direction.
1350 // TODO: implement reference frame.
1351 public void ComputeAngularDeflection()
1352 {
1353 // Since angularMotorUp and angularDeflection are computed independently, they will calculate
1354 // approximately the same X or Y correction. When added together (when contributions are combined)
1355 // this creates an over-correction and then wabbling as the target is overshot.
1356 // TODO: rethink how the different correction computations inter-relate.
1357
1358 if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
1359 {
1360 Vector3 deflectContributionV = Vector3.Zero;
1361
1362 // The direction the vehicle is moving
1363 Vector3 movingDirection = VehicleVelocity;
1364 movingDirection.Normalize();
1365
1366 // If the vehicle is going backward, it is still pointing forward
1367 movingDirection *= Math.Sign(VehicleForwardSpeed);
1368
1369 // The direction the vehicle is pointing
1370 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1371 pointingDirection.Normalize();
1372
1373 // The difference between what is and what should be.
1374 Vector3 deflectionError = movingDirection - pointingDirection;
1375
1376 // Don't try to correct very large errors (not our job)
1377 // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X);
1378 // if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = PIOverTwo * Math.Sign(deflectionError.Y);
1379 // if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = PIOverTwo * Math.Sign(deflectionError.Z);
1380 if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f;
1381 if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f;
1382 if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f;
1383
1384 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1385
1386 // Scale the correction by recovery timescale and efficiency
1387 deflectContributionV = (-deflectionError) * m_angularDeflectionEfficiency;
1388 deflectContributionV /= m_angularDeflectionTimescale;
1389
1390 VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1391
1392 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1393 Prim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV);
1394 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}",
1395 Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale);
1396 }
1397 }
1398
1399 // Angular change to rotate the vehicle around the Z axis when the vehicle
1400 // is tipped around the X axis.
1401 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1402 // The vertical attractor feature must be enabled in order for the banking behavior to
1403 // function. The way banking works is this: a rotation around the vehicle's roll-axis will
1404 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
1405 // of the yaw effect will be proportional to the
1406 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1407 // velocity along its preferred axis of motion.
1408 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
1409 // positive rotation (by the right-hand rule) about the roll-axis will effect a
1410 // (negative) torque around the yaw-axis, making it turn to the right--that is the
1411 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
1412 // Negating the banking coefficient will make it so that the vehicle leans to the
1413 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
1414 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
1415 // banking vehicles do what you want rather than what the laws of physics allow.
1416 // For example, consider a real motorcycle...it must be moving forward in order for
1417 // it to turn while banking, however video-game motorcycles are often configured
1418 // to turn in place when at a dead stop--because they are often easier to control
1419 // that way using the limited interface of the keyboard or game controller. The
1420 // VEHICLE_BANKING_MIX enables combinations of both realistic and non-realistic
1421 // banking by functioning as a slider between a banking that is correspondingly
1422 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
1423 // banking effect depends only on the vehicle's rotation about its roll-axis compared
1424 // to "dynamic" where the banking is also proportional to its velocity along its
1425 // roll-axis. Finding the best value of the "mixture" will probably require trial and error.
1426 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the
1427 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1428 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1429 // make a sluggish vehicle by giving it a timescale of several seconds.
1430 public void ComputeAngularBanking()
1431 {
1432 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1019 { 1433 {
1020 // Apply to the body. 1434 Vector3 bankingContributionV = Vector3.Zero;
1021 // The above calculates the absolute angular velocity needed. Angular velocity is massless. 1435
1022 // Since we are stuffing the angular velocity directly into the object, the computed 1436 // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented.
1023 // velocity needs to be scaled by the timestep. 1437 // As the vehicle rolls to the right or left, the Y value will increase from
1024 Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) - Prim.ForceRotationalVelocity); 1438 // zero (straight up) to 1 or -1 (full tilt right or left)
1025 Prim.ForceRotationalVelocity = applyAngularForce; 1439 Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation;
1026 1440
1027 // Decay the angular movement for next time 1441 // Figure out the yaw value for this much roll.
1028 Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; 1442 // Squared because that seems to give a good value
1029 m_lastAngularVelocity *= Vector3.One - decayamount; 1443 float yawAngle = (float)Math.Asin(rollComponents.Y * rollComponents.Y) * m_bankingEfficiency;
1030 1444
1031 VDetailLog("{0},MoveAngular,done,newRotVel={1},decay={2},lastAngular={3}", 1445 // actual error = static turn error + dynamic turn error
1032 Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity); 1446 float mixedYawAngle = yawAngle * (1f - m_bankingMix) + yawAngle * m_bankingMix * VehicleForwardSpeed;
1447
1448 // TODO: the banking effect should not go to infinity but what to limit it to?
1449 mixedYawAngle = ClampInRange(-20f, mixedYawAngle, 20f);
1450
1451 // Build the force vector to change rotation from what it is to what it should be
1452 bankingContributionV.Z = -mixedYawAngle;
1453
1454 // Don't do it all at once.
1455 bankingContributionV /= m_bankingTimescale;
1456
1457 VehicleRotationalVelocity += bankingContributionV * VehicleOrientation;
1458
1459 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}",
1460 Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV);
1033 } 1461 }
1034 } //end MoveAngular 1462 }
1035 1463
1464 // This is from previous instantiations of XXXDynamics.cs.
1465 // Applies roll reference frame.
1466 // TODO: is this the right way to separate the code to do this operation?
1467 // Should this be in MoveAngular()?
1036 internal void LimitRotation(float timestep) 1468 internal void LimitRotation(float timestep)
1037 { 1469 {
1038 Quaternion rotq = Prim.ForceOrientation; 1470 Quaternion rotq = VehicleOrientation;
1039 Quaternion m_rot = rotq; 1471 Quaternion m_rot = rotq;
1040 if (m_RollreferenceFrame != Quaternion.Identity) 1472 if (m_RollreferenceFrame != Quaternion.Identity)
1041 { 1473 {
@@ -1063,12 +1495,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1063 } 1495 }
1064 if (rotq != m_rot) 1496 if (rotq != m_rot)
1065 { 1497 {
1066 Prim.ForceOrientation = m_rot; 1498 VehicleOrientation = m_rot;
1067 VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); 1499 VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot);
1068 } 1500 }
1069 1501
1070 } 1502 }
1071 1503
1504 private float ClampInRange(float low, float val, float high)
1505 {
1506 return Math.Max(low, Math.Min(val, high));
1507 // return Utils.Clamp(val, low, high);
1508 }
1509
1072 // Invoke the detailed logger and output something if it's enabled. 1510 // Invoke the detailed logger and output something if it's enabled.
1073 private void VDetailLog(string msg, params Object[] args) 1511 private void VDetailLog(string msg, params Object[] args)
1074 { 1512 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 0df4310..1e3e5d8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -32,6 +32,15 @@ using OMV = OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35
36// A BSPrim can get individual information about its linkedness attached
37// to it through an instance of a subclass of LinksetInfo.
38// Each type of linkset will define the information needed for its type.
39public abstract class BSLinksetInfo
40{
41 public virtual void Clear() { }
42}
43
35public abstract class BSLinkset 44public abstract class BSLinkset
36{ 45{
37 // private static string LogHeader = "[BULLETSIM LINKSET]"; 46 // private static string LogHeader = "[BULLETSIM LINKSET]";
@@ -47,7 +56,7 @@ public abstract class BSLinkset
47 { 56 {
48 BSLinkset ret = null; 57 BSLinkset ret = null;
49 58
50 switch ((int)physScene.Params.linksetImplementation) 59 switch ((int)BSParam.LinksetImplementation)
51 { 60 {
52 case (int)LinksetImplementation.Constraint: 61 case (int)LinksetImplementation.Constraint:
53 ret = new BSLinksetConstraints(physScene, parent); 62 ret = new BSLinksetConstraints(physScene, parent);
@@ -87,22 +96,8 @@ public abstract class BSLinkset
87 return BSPhysicsShapeType.SHAPE_UNKNOWN; 96 return BSPhysicsShapeType.SHAPE_UNKNOWN;
88 } 97 }
89 98
90 // Linksets move around the children so the linkset might need to compute the child position
91 public virtual OMV.Vector3 Position(BSPhysObject member)
92 { return member.RawPosition; }
93 public virtual OMV.Quaternion Orientation(BSPhysObject member)
94 { return member.RawOrientation; }
95 // TODO: does this need to be done for Velocity and RotationalVelocityy?
96
97 // We keep the prim's mass in the linkset structure since it could be dependent on other prims 99 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
98 protected float m_mass; 100 public float LinksetMass { get; protected set; }
99 public float LinksetMass
100 {
101 get
102 {
103 return m_mass;
104 }
105 }
106 101
107 public virtual bool LinksetIsColliding { get { return false; } } 102 public virtual bool LinksetIsColliding { get { return false; } }
108 103
@@ -116,7 +111,7 @@ public abstract class BSLinkset
116 get { return ComputeLinksetGeometricCenter(); } 111 get { return ComputeLinksetGeometricCenter(); }
117 } 112 }
118 113
119 protected void Initialize(BSScene scene, BSPhysObject parent) 114 protected BSLinkset(BSScene scene, BSPhysObject parent)
120 { 115 {
121 // A simple linkset of one (no children) 116 // A simple linkset of one (no children)
122 LinksetID = m_nextLinksetID++; 117 LinksetID = m_nextLinksetID++;
@@ -126,7 +121,8 @@ public abstract class BSLinkset
126 PhysicsScene = scene; 121 PhysicsScene = scene;
127 LinksetRoot = parent; 122 LinksetRoot = parent;
128 m_children = new HashSet<BSPhysObject>(); 123 m_children = new HashSet<BSPhysObject>();
129 m_mass = parent.RawMass; 124 LinksetMass = parent.RawMass;
125 Rebuilding = false;
130 } 126 }
131 127
132 // Link to a linkset where the child knows the parent. 128 // Link to a linkset where the child knows the parent.
@@ -140,7 +136,7 @@ public abstract class BSLinkset
140 // Don't add the root to its own linkset 136 // Don't add the root to its own linkset
141 if (!IsRoot(child)) 137 if (!IsRoot(child))
142 AddChildToLinkset(child); 138 AddChildToLinkset(child);
143 m_mass = ComputeLinksetMass(); 139 LinksetMass = ComputeLinksetMass();
144 } 140 }
145 return this; 141 return this;
146 } 142 }
@@ -156,13 +152,15 @@ public abstract class BSLinkset
156 if (IsRoot(child)) 152 if (IsRoot(child))
157 { 153 {
158 // Cannot remove the root from a linkset. 154 // Cannot remove the root from a linkset.
155 child.PositionDisplacement = OMV.Vector3.Zero;
159 return this; 156 return this;
160 } 157 }
161 RemoveChildFromLinkset(child); 158 RemoveChildFromLinkset(child);
162 m_mass = ComputeLinksetMass(); 159 LinksetMass = ComputeLinksetMass();
163 } 160 }
164 161
165 // The child is down to a linkset of just itself 162 // The child is down to a linkset of just itself
163 child.PositionDisplacement = OMV.Vector3.Zero;
166 return BSLinkset.Factory(PhysicsScene, child); 164 return BSLinkset.Factory(PhysicsScene, child);
167 } 165 }
168 166
@@ -219,7 +217,7 @@ public abstract class BSLinkset
219 // I am the root of a linkset and a new child is being added 217 // I am the root of a linkset and a new child is being added
220 // Called while LinkActivity is locked. 218 // Called while LinkActivity is locked.
221 protected abstract void AddChildToLinkset(BSPhysObject child); 219 protected abstract void AddChildToLinkset(BSPhysObject child);
222 220
223 // I am the root of a linkset and one of my children is being removed. 221 // I am the root of a linkset and one of my children is being removed.
224 // Safe to call even if the child is not really in my linkset. 222 // Safe to call even if the child is not really in my linkset.
225 protected abstract void RemoveChildFromLinkset(BSPhysObject child); 223 protected abstract void RemoveChildFromLinkset(BSPhysObject child);
@@ -227,7 +225,14 @@ public abstract class BSLinkset
227 // When physical properties are changed the linkset needs to recalculate 225 // When physical properties are changed the linkset needs to recalculate
228 // its internal properties. 226 // its internal properties.
229 // May be called at runtime or taint-time. 227 // May be called at runtime or taint-time.
230 public abstract void Refresh(BSPhysObject requestor); 228 public virtual void Refresh(BSPhysObject requestor)
229 {
230 LinksetMass = ComputeLinksetMass();
231 }
232
233 // Flag denoting the linkset is in the process of being rebuilt.
234 // Used to know not the schedule a rebuild in the middle of a rebuild.
235 protected bool Rebuilding { get; set; }
231 236
232 // The object is going dynamic (physical). Do any setup necessary 237 // The object is going dynamic (physical). Do any setup necessary
233 // for a dynamic linkset. 238 // for a dynamic linkset.
@@ -245,8 +250,9 @@ public abstract class BSLinkset
245 250
246 // Called when a parameter update comes from the physics engine for any object 251 // Called when a parameter update comes from the physics engine for any object
247 // of the linkset is received. 252 // of the linkset is received.
253 // Passed flag is update came from physics engine (true) or the user (false).
248 // Called at taint-time!! 254 // Called at taint-time!!
249 public abstract void UpdateProperties(BSPhysObject physObject); 255 public abstract void UpdateProperties(UpdatedProperties whichUpdated, BSPhysObject physObject);
250 256
251 // Routine used when rebuilding the body of the root of the linkset 257 // Routine used when rebuilding the body of the root of the linkset
252 // Destroy all the constraints have have been made to root. 258 // Destroy all the constraints have have been made to root.
@@ -255,11 +261,6 @@ public abstract class BSLinkset
255 // Called at taint-time!! 261 // Called at taint-time!!
256 public abstract bool RemoveBodyDependencies(BSPrim child); 262 public abstract bool RemoveBodyDependencies(BSPrim child);
257 263
258 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
259 // this routine will restore the removed constraints.
260 // Called at taint-time!!
261 public abstract void RestoreBodyDependencies(BSPrim child);
262
263 // ================================================================ 264 // ================================================================
264 protected virtual float ComputeLinksetMass() 265 protected virtual float ComputeLinksetMass()
265 { 266 {
@@ -306,7 +307,7 @@ public abstract class BSLinkset
306 307
307 foreach (BSPhysObject bp in m_children) 308 foreach (BSPhysObject bp in m_children)
308 { 309 {
309 com += bp.Position * bp.RawMass; 310 com += bp.Position;
310 } 311 }
311 com /= (m_children.Count + 1); 312 com /= (m_children.Count + 1);
312 } 313 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index b9c2cf9..0c4db40 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -28,22 +28,79 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30 30
31using OpenSim.Framework;
32
31using OMV = OpenMetaverse; 33using OMV = OpenMetaverse;
32 34
33namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
34{ 36{
37
38// When a child is linked, the relationship position of the child to the parent
39// is remembered so the child's world position can be recomputed when it is
40// removed from the linkset.
41sealed class BSLinksetCompoundInfo : BSLinksetInfo
42{
43 public int Index;
44 public OMV.Vector3 OffsetFromRoot;
45 public OMV.Vector3 OffsetFromCenterOfMass;
46 public OMV.Quaternion OffsetRot;
47 public BSLinksetCompoundInfo(int indx, OMV.Vector3 p, OMV.Quaternion r)
48 {
49 Index = indx;
50 OffsetFromRoot = p;
51 OffsetFromCenterOfMass = p;
52 OffsetRot = r;
53 }
54 // 'centerDisplacement' is the distance from the root the the center-of-mass (Bullet 'zero' of the shape)
55 public BSLinksetCompoundInfo(int indx, BSPhysObject root, BSPhysObject child, OMV.Vector3 centerDisplacement)
56 {
57 // Each child position and rotation is given relative to the center-of-mass.
58 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(root.RawOrientation);
59 OMV.Vector3 displacementFromRoot = (child.RawPosition - root.RawPosition) * invRootOrientation;
60 OMV.Vector3 displacementFromCOM = displacementFromRoot - centerDisplacement;
61 OMV.Quaternion displacementRot = child.RawOrientation * invRootOrientation;
62
63 // Save relative position for recomputing child's world position after moving linkset.
64 Index = indx;
65 OffsetFromRoot = displacementFromRoot;
66 OffsetFromCenterOfMass = displacementFromCOM;
67 OffsetRot = displacementRot;
68 }
69 public override void Clear()
70 {
71 Index = 0;
72 OffsetFromRoot = OMV.Vector3.Zero;
73 OffsetFromCenterOfMass = OMV.Vector3.Zero;
74 OffsetRot = OMV.Quaternion.Identity;
75 }
76 public override string ToString()
77 {
78 StringBuilder buff = new StringBuilder();
79 buff.Append("<i=");
80 buff.Append(Index.ToString());
81 buff.Append(",p=");
82 buff.Append(OffsetFromRoot.ToString());
83 buff.Append(",m=");
84 buff.Append(OffsetFromCenterOfMass.ToString());
85 buff.Append(",r=");
86 buff.Append(OffsetRot.ToString());
87 buff.Append(">");
88 return buff.ToString();
89 }
90};
91
35public sealed class BSLinksetCompound : BSLinkset 92public sealed class BSLinksetCompound : BSLinkset
36{ 93{
37 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; 94 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
38 95
39 public BSLinksetCompound(BSScene scene, BSPhysObject parent) 96 public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent)
40 { 97 {
41 base.Initialize(scene, parent);
42 } 98 }
43 99
44 // For compound implimented linksets, if there are children, use compound shape for the root. 100 // For compound implimented linksets, if there are children, use compound shape for the root.
45 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) 101 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
46 { 102 {
103 // Returning 'unknown' means we don't have a preference.
47 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 104 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
48 if (IsRoot(requestor) && HasAnyChildren) 105 if (IsRoot(requestor) && HasAnyChildren)
49 { 106 {
@@ -55,27 +112,33 @@ public sealed class BSLinksetCompound : BSLinkset
55 112
56 // When physical properties are changed the linkset needs to recalculate 113 // When physical properties are changed the linkset needs to recalculate
57 // its internal properties. 114 // its internal properties.
58 // This is queued in the 'post taint' queue so the
59 // refresh will happen once after all the other taints are applied.
60 public override void Refresh(BSPhysObject requestor) 115 public override void Refresh(BSPhysObject requestor)
61 { 116 {
62 // External request for Refresh (from BSPrim) is not necessary 117 base.Refresh(requestor);
63 // InternalRefresh(requestor); 118
119 // Something changed so do the rebuilding thing
120 // ScheduleRebuild();
64 } 121 }
65 122
66 private void InternalRefresh(BSPhysObject requestor) 123 // Schedule a refresh to happen after all the other taint processing.
124 private void ScheduleRebuild(BSPhysObject requestor)
67 { 125 {
68 DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); 126 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}",
69 // Queue to happen after all the other taint processing 127 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren));
70 PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() 128 // When rebuilding, it is possible to set properties that would normally require a rebuild.
129 // If already rebuilding, don't request another rebuild.
130 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
131 if (!Rebuilding && HasAnyChildren)
71 { 132 {
72 if (IsRoot(requestor) && HasAnyChildren) 133 PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
73 RecomputeLinksetCompound(); 134 {
74 }); 135 if (HasAnyChildren)
136 RecomputeLinksetCompound();
137 });
138 }
75 } 139 }
76 140
77 // The object is going dynamic (physical). Do any setup necessary 141 // The object is going dynamic (physical). Do any setup necessary for a dynamic linkset.
78 // for a dynamic linkset.
79 // Only the state of the passed object can be modified. The rest of the linkset 142 // Only the state of the passed object can be modified. The rest of the linkset
80 // has not yet been fully constructed. 143 // has not yet been fully constructed.
81 // Return 'true' if any properties updated on the passed object. 144 // Return 'true' if any properties updated on the passed object.
@@ -84,12 +147,22 @@ public sealed class BSLinksetCompound : BSLinkset
84 { 147 {
85 bool ret = false; 148 bool ret = false;
86 DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); 149 DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
87 if (!IsRoot(child)) 150 if (IsRoot(child))
151 {
152 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
153 ScheduleRebuild(LinksetRoot);
154 }
155 else
88 { 156 {
89 // Physical children are removed from the world as the shape ofthe root compound 157 // The origional prims are removed from the world as the shape of the root compound
90 // shape takes over. 158 // shape takes over.
91 BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 159 PhysicsScene.PE.AddToCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
92 BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); 160 PhysicsScene.PE.ForceActivationState(child.PhysBody, ActivationState.DISABLE_SIMULATION);
161 // We don't want collisions from the old linkset children.
162 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
163
164 child.PhysBody.collisionType = CollisionType.LinksetChild;
165
93 ret = true; 166 ret = true;
94 } 167 }
95 return ret; 168 return ret;
@@ -104,33 +177,114 @@ public sealed class BSLinksetCompound : BSLinkset
104 { 177 {
105 bool ret = false; 178 bool ret = false;
106 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); 179 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
107 if (!IsRoot(child)) 180 if (IsRoot(child))
181 {
182 ScheduleRebuild(LinksetRoot);
183 }
184 else
108 { 185 {
109 // The non-physical children can come back to life. 186 // The non-physical children can come back to life.
110 BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 187 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
111 // Don't force activation so setting of DISABLE_SIMULATION can stay. 188
112 BulletSimAPI.Activate2(child.PhysBody.ptr, false); 189 child.PhysBody.collisionType = CollisionType.LinksetChild;
190
191 // Don't force activation so setting of DISABLE_SIMULATION can stay if used.
192 PhysicsScene.PE.Activate(child.PhysBody, false);
113 ret = true; 193 ret = true;
114 } 194 }
115 return ret; 195 return ret;
116 } 196 }
117 197
118 // Called at taint-time!! 198 // 'physicalUpdate' is true if these changes came directly from the physics engine. Don't need to rebuild then.
119 public override void UpdateProperties(BSPhysObject updated) 199 // Called at taint-time.
200 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPhysObject updated)
120 { 201 {
121 // Nothing to do for constraints on property updates 202 // The user moving a child around requires the rebuilding of the linkset compound shape
122 } 203 // One problem is this happens when a border is crossed -- the simulator implementation
204 // stores the position into the group which causes the move of the object
205 // but it also means all the child positions get updated.
206 // What would cause an unnecessary rebuild so we make sure the linkset is in a
207 // region before bothering to do a rebuild.
208 if (!IsRoot(updated) && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
209 {
210 // If a child of the linkset is updating only the position or rotation, that can be done
211 // without rebuilding the linkset.
212 // If a handle for the child can be fetch, we update the child here. If a rebuild was
213 // scheduled by someone else, the rebuild will just replace this setting.
214
215 bool updatedChild = false;
216 // Anything other than updating position or orientation usually means a physical update
217 // and that is caused by us updating the object.
218 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
219 {
220 // Gather the child info. It might not be there if the linkset is in transition.
221 BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo;
222 if (lsi != null)
223 {
224 // Since the child moved or rotationed, it needs a new relative position within the linkset
225 BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement);
226 updated.LinksetInfo = newLsi;
123 227
124 // The children move around in relationship to the root. 228 // Find the physical instance of the child
125 // Just grab the current values of wherever it is right now. 229 if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
126 public override OMV.Vector3 Position(BSPhysObject member) 230 {
127 { 231 // It is possible that the linkset is still under construction and the child is not yet
128 return BulletSimAPI.GetPosition2(member.PhysBody.ptr); 232 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
129 } 233 // build the whole thing with the new position or rotation.
234 // The index must be checked because Bullet references the child array but does no validity
235 // checking of the child index passed.
236 int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
237 if (lsi.Index < numLinksetChildren)
238 {
239 BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index);
240 if (linksetChildShape.HasPhysicalShape)
241 {
242 // Found the child shape within the compound shape
243 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index,
244 newLsi.OffsetFromCenterOfMass,
245 newLsi.OffsetRot,
246 true /* shouldRecalculateLocalAabb */);
247 updatedChild = true;
248 DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}",
249 updated.LocalID, whichUpdated, newLsi);
250 }
251 else // DEBUG DEBUG
252 { // DEBUG DEBUG
253 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
254 updated.LocalID, linksetChildShape);
255 } // DEBUG DEBUG
256 }
257 else // DEBUG DEBUG
258 { // DEBUG DEBUG
259 // the child is not yet in the compound shape. This is non-fatal.
260 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
261 updated.LocalID, numLinksetChildren, lsi.Index);
262 } // DEBUG DEBUG
263 }
264 else // DEBUG DEBUG
265 { // DEBUG DEBUG
266 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID);
267 } // DEBUG DEBUG
268 }
269 else // DEBUG DEBUG
270 { // DEBUG DEBUG
271 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noLinkSetInfo,rootPhysShape={1}",
272 updated.LocalID, LinksetRoot.PhysShape);
273 } // DEBUG DEBUG
130 274
131 public override OMV.Quaternion Orientation(BSPhysObject member) 275 if (!updatedChild)
132 { 276 {
133 return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); 277 // If couldn't do the individual child, the linkset needs a rebuild to incorporate the new child info.
278 // Note: there are several ways through this code that will not update the child if
279 // the linkset is being rebuilt. In this case, scheduling a rebuild is a NOOP since
280 // there will already be a rebuild scheduled.
281 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}",
282 updated.LocalID, whichUpdated);
283 updated.LinksetInfo = null; // setting to 'null' causes relative position to be recomputed.
284 ScheduleRebuild(updated);
285 }
286 }
287 }
134 } 288 }
135 289
136 // Routine called when rebuilding the body of some member of the linkset. 290 // Routine called when rebuilding the body of some member of the linkset.
@@ -142,24 +296,65 @@ public sealed class BSLinksetCompound : BSLinkset
142 bool ret = false; 296 bool ret = false;
143 297
144 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", 298 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
145 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); 299 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child));
146 300
147 if (!IsRoot(child)) 301 if (!IsRoot(child))
148 { 302 {
149 // Cause the current shape to be freed and the new one to be built. 303 // Because it is a convenient time, recompute child world position and rotation based on
150 InternalRefresh(LinksetRoot); 304 // its position in the linkset.
151 ret = true; 305 RecomputeChildWorldPosition(child, true /* inTaintTime */);
306 child.LinksetInfo = null;
152 } 307 }
153 308
309 // Cannot schedule a refresh/rebuild here because this routine is called when
310 // the linkset is being rebuilt.
311 // InternalRefresh(LinksetRoot);
312
154 return ret; 313 return ret;
155 } 314 }
156 315
157 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', 316 // When the linkset is built, the child shape is added to the compound shape relative to the
158 // this routine will restore the removed constraints. 317 // root shape. The linkset then moves around but this does not move the actual child
159 // Called at taint-time!! 318 // prim. The child prim's location must be recomputed based on the location of the root shape.
160 public override void RestoreBodyDependencies(BSPrim child) 319 private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime)
161 { 320 {
162 // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. 321 // For the moment (20130201), disable this computation (converting the child physical addr back to
322 // a region address) until we have a good handle on center-of-mass offsets and what the physics
323 // engine moving a child actually means.
324 // The simulator keeps track of where children should be as the linkset moves. Setting
325 // the pos/rot here does not effect that knowledge as there is no good way for the
326 // physics engine to send the simulator an update for a child.
327
328 /*
329 BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
330 if (lci != null)
331 {
332 if (inTaintTime)
333 {
334 OMV.Vector3 oldPos = child.RawPosition;
335 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetFromRoot;
336 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
337 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
338 child.LocalID, oldPos, lci, child.RawPosition);
339 }
340 else
341 {
342 // TaintedObject is not used here so the raw position is set now and not at taint-time.
343 child.Position = LinksetRoot.RawPosition + lci.OffsetFromRoot;
344 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
345 }
346 }
347 else
348 {
349 // This happens when children have been added to the linkset but the linkset
350 // has not been constructed yet. So like, at taint time, adding children to a linkset
351 // and then changing properties of the children (makePhysical, for instance)
352 // but the post-print action of actually rebuilding the linkset has not yet happened.
353 // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}",
354 // LogHeader, child.LocalID);
355 DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
356 }
357 */
163 } 358 }
164 359
165 // ================================================================ 360 // ================================================================
@@ -174,24 +369,26 @@ public sealed class BSLinksetCompound : BSLinkset
174 369
175 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 370 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
176 371
177 // Cause constraints and assorted properties to be recomputed before the next simulation step. 372 // Rebuild the compound shape with the new child shape included
178 InternalRefresh(LinksetRoot); 373 ScheduleRebuild(child);
179 } 374 }
180 return; 375 return;
181 } 376 }
182 377
183 // Remove the specified child from the linkset. 378 // Remove the specified child from the linkset.
184 // Safe to call even if the child is not really in my linkset. 379 // Safe to call even if the child is not really in the linkset.
185 protected override void RemoveChildFromLinkset(BSPhysObject child) 380 protected override void RemoveChildFromLinkset(BSPhysObject child)
186 { 381 {
187 if (m_children.Remove(child)) 382 if (m_children.Remove(child))
188 { 383 {
189 DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", 384 DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
190 child.LocalID, 385 child.LocalID,
191 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), 386 LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString,
192 child.LocalID, child.PhysBody.ptr.ToString("X")); 387 child.LocalID, child.PhysBody.AddrString);
193 388
194 // Cause the child's body to be rebuilt and thus restored to normal operation 389 // Cause the child's body to be rebuilt and thus restored to normal operation
390 RecomputeChildWorldPosition(child, false);
391 child.LinksetInfo = null;
195 child.ForceBodyShapeRebuild(false); 392 child.ForceBodyShapeRebuild(false);
196 393
197 if (!HasAnyChildren) 394 if (!HasAnyChildren)
@@ -201,8 +398,8 @@ public sealed class BSLinksetCompound : BSLinkset
201 } 398 }
202 else 399 else
203 { 400 {
204 // Schedule a rebuild of the linkset before the next simulation tick. 401 // Rebuild the compound shape with the child removed
205 InternalRefresh(LinksetRoot); 402 ScheduleRebuild(LinksetRoot);
206 } 403 }
207 } 404 }
208 return; 405 return;
@@ -213,63 +410,112 @@ public sealed class BSLinksetCompound : BSLinkset
213 // Constraint linksets are rebuilt every time. 410 // Constraint linksets are rebuilt every time.
214 // Note that this works for rebuilding just the root after a linkset is taken apart. 411 // Note that this works for rebuilding just the root after a linkset is taken apart.
215 // Called at taint time!! 412 // Called at taint time!!
413 private bool disableCOM = true; // DEBUG DEBUG: disable until we get this debugged
216 private void RecomputeLinksetCompound() 414 private void RecomputeLinksetCompound()
217 { 415 {
218 // Cause the root shape to be rebuilt as a compound object with just the root in it 416 try
219 LinksetRoot.ForceBodyShapeRebuild(true);
220
221 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
222 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
223
224 // Add a shape for each of the other children in the linkset
225 ForEachMember(delegate(BSPhysObject cPrim)
226 { 417 {
227 if (!IsRoot(cPrim)) 418 // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.)
419 Rebuilding = true;
420
421 // Cause the root shape to be rebuilt as a compound object with just the root in it
422 LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime */);
423
424 // The center of mass for the linkset is the geometric center of the group.
425 // Compute a displacement for each component so it is relative to the center-of-mass.
426 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
427 OMV.Vector3 centerOfMass;
428 OMV.Vector3 centerDisplacement = OMV.Vector3.Zero;
429 if (disableCOM) // DEBUG DEBUG
430 { // DEBUG DEBUG
431 centerOfMass = LinksetRoot.RawPosition; // DEBUG DEBUG
432 LinksetRoot.PositionDisplacement = OMV.Vector3.Zero;
433 } // DEBUG DEBUG
434 else
228 { 435 {
229 // Each child position and rotation is given relative to the root. 436 centerOfMass = ComputeLinksetCenterOfMass();
230 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); 437 // 'centerDisplacement' is the value to *add* to all the shape offsets
231 OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; 438 centerDisplacement = LinksetRoot.RawPosition - centerOfMass;
232 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; 439
440 // Since we're displacing the center of the shape, we need to move the body in the world
441 LinksetRoot.PositionDisplacement = centerDisplacement;
442
443 // This causes the root prim position to be set properly based on the new PositionDisplacement
444 LinksetRoot.ForcePosition = LinksetRoot.RawPosition;
445 // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM
446 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false);
447 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
448 LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement);
449 }
233 450
234 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", 451 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
235 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot); 452 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
236 453
237 if (cPrim.PhysShape.isNativeShape) 454 // Add a shape for each of the other children in the linkset
238 { 455 int memberIndex = 1;
239 // Native shapes are not shared so we need to create a new one. 456 ForEachMember(delegate(BSPhysObject cPrim)
240 // A mesh or hull is created because scale is not available on a native shape. 457 {
241 // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?) 458 if (!IsRoot(cPrim))
242 BulletShape saveShape = cPrim.PhysShape;
243 cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape
244 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
245 BulletShape newShape = cPrim.PhysShape;
246 cPrim.PhysShape = saveShape;
247 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot);
248 }
249 else
250 { 459 {
251 // For the shared shapes (meshes and hulls), just use the shape in the child. 460 // Compute the displacement of the child from the root of the linkset.
252 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) 461 // This info is saved in the child prim so the relationship does not
462 // change over time and the new child position can be computed
463 // when the linkset is being disassembled (the linkset may have moved).
464 BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
465 if (lci == null)
253 { 466 {
254 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", 467 lci = new BSLinksetCompoundInfo(memberIndex, LinksetRoot, cPrim, centerDisplacement);
255 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); 468 cPrim.LinksetInfo = lci;
469 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
256 } 470 }
257 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot);
258 }
259 }
260 return false; // 'false' says to move onto the next child in the list
261 });
262 471
263 // With all of the linkset packed into the root prim, it has the mass of everyone. 472 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}",
264 float linksetMass = LinksetMass; 473 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci);
265 LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
266 474
267 BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr); 475 if (cPrim.PhysShape.isNativeShape)
476 {
477 // A native shape is turned into a hull collision shape because native
478 // shapes are not shared so we have to hullify it so it will be tracked
479 // and freed at the correct time. This also solves the scaling problem
480 // (native shapes scaled but hull/meshes are assumed to not be).
481 // TODO: decide of the native shape can just be used in the compound shape.
482 // Use call to CreateGeomNonSpecial().
483 BulletShape saveShape = cPrim.PhysShape;
484 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
485 // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
486 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
487 BulletShape newShape = cPrim.PhysShape;
488 cPrim.PhysShape = saveShape;
489 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
490 }
491 else
492 {
493 // For the shared shapes (meshes and hulls), just use the shape in the child.
494 // The reference count added here will be decremented when the compound shape
495 // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
496 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
497 {
498 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
499 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
500 }
501 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
502 }
503 lci.Index = memberIndex;
504 memberIndex++;
505 }
506 return false; // 'false' says to move onto the next child in the list
507 });
268 508
269 // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets. 509 // With all of the linkset packed into the root prim, it has the mass of everyone.
270 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, 510 LinksetMass = ComputeLinksetMass();
271 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); 511 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
512 }
513 finally
514 {
515 Rebuilding = false;
516 }
272 517
518 PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape);
273 } 519 }
274} 520}
275} \ No newline at end of file 521} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index c855fda..3011465 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -36,9 +36,8 @@ public sealed class BSLinksetConstraints : BSLinkset
36{ 36{
37 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; 37 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
38 38
39 public BSLinksetConstraints(BSScene scene, BSPhysObject parent) 39 public BSLinksetConstraints(BSScene scene, BSPhysObject parent) : base(scene, parent)
40 { 40 {
41 base.Initialize(scene, parent);
42 } 41 }
43 42
44 // When physical properties are changed the linkset needs to recalculate 43 // When physical properties are changed the linkset needs to recalculate
@@ -47,12 +46,17 @@ public sealed class BSLinksetConstraints : BSLinkset
47 // refresh will happen once after all the other taints are applied. 46 // refresh will happen once after all the other taints are applied.
48 public override void Refresh(BSPhysObject requestor) 47 public override void Refresh(BSPhysObject requestor)
49 { 48 {
50 // Queue to happen after all the other taint processing 49 base.Refresh(requestor);
51 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() 50
52 { 51 if (HasAnyChildren && IsRoot(requestor))
53 if (HasAnyChildren && IsRoot(requestor)) 52 {
54 RecomputeLinksetConstraints(); 53 // Queue to happen after all the other taint processing
55 }); 54 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
55 {
56 if (HasAnyChildren && IsRoot(requestor))
57 RecomputeLinksetConstraints();
58 });
59 }
56 } 60 }
57 61
58 // The object is going dynamic (physical). Do any setup necessary 62 // The object is going dynamic (physical). Do any setup necessary
@@ -79,23 +83,11 @@ public sealed class BSLinksetConstraints : BSLinkset
79 } 83 }
80 84
81 // Called at taint-time!! 85 // Called at taint-time!!
82 public override void UpdateProperties(BSPhysObject updated) 86 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPhysObject pObj)
83 { 87 {
84 // Nothing to do for constraints on property updates 88 // Nothing to do for constraints on property updates
85 } 89 }
86 90
87 // The children of the linkset are moved around by the constraints.
88 // Just grab the current values of wherever it is right now.
89 public override OMV.Vector3 Position(BSPhysObject member)
90 {
91 return BulletSimAPI.GetPosition2(member.PhysBody.ptr);
92 }
93
94 public override OMV.Quaternion Orientation(BSPhysObject member)
95 {
96 return BulletSimAPI.GetOrientation2(member.PhysBody.ptr);
97 }
98
99 // Routine called when rebuilding the body of some member of the linkset. 91 // Routine called when rebuilding the body of some member of the linkset.
100 // Destroy all the constraints have have been made to root and set 92 // Destroy all the constraints have have been made to root and set
101 // up to rebuild the constraints before the next simulation step. 93 // up to rebuild the constraints before the next simulation step.
@@ -106,7 +98,7 @@ public sealed class BSLinksetConstraints : BSLinkset
106 bool ret = false; 98 bool ret = false;
107 99
108 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", 100 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
109 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); 101 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString);
110 102
111 lock (m_linksetActivityLock) 103 lock (m_linksetActivityLock)
112 { 104 {
@@ -118,14 +110,6 @@ public sealed class BSLinksetConstraints : BSLinkset
118 return ret; 110 return ret;
119 } 111 }
120 112
121 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
122 // this routine will restore the removed constraints.
123 // Called at taint-time!!
124 public override void RestoreBodyDependencies(BSPrim child)
125 {
126 // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints.
127 }
128
129 // ================================================================ 113 // ================================================================
130 114
131 // Add a new child to the linkset. 115 // Add a new child to the linkset.
@@ -155,8 +139,8 @@ public sealed class BSLinksetConstraints : BSLinkset
155 139
156 DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", 140 DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
157 childx.LocalID, 141 childx.LocalID,
158 rootx.LocalID, rootx.PhysBody.ptr.ToString("X"), 142 rootx.LocalID, rootx.PhysBody.AddrString,
159 childx.LocalID, childx.PhysBody.ptr.ToString("X")); 143 childx.LocalID, childx.PhysBody.AddrString);
160 144
161 PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() 145 PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate()
162 { 146 {
@@ -195,8 +179,8 @@ public sealed class BSLinksetConstraints : BSLinkset
195 179
196 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", 180 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
197 rootPrim.LocalID, 181 rootPrim.LocalID,
198 rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), 182 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
199 childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X"), 183 childPrim.LocalID, childPrim.PhysBody.AddrString,
200 rootPrim.Position, childPrim.Position, midPoint); 184 rootPrim.Position, childPrim.Position, midPoint);
201 185
202 // create a constraint that allows no freedom of movement between the two objects 186 // create a constraint that allows no freedom of movement between the two objects
@@ -239,14 +223,14 @@ public sealed class BSLinksetConstraints : BSLinkset
239 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 223 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
240 224
241 // tweek the constraint to increase stability 225 // tweek the constraint to increase stability
242 constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); 226 constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset));
243 constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), 227 constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor),
244 PhysicsScene.Params.linkConstraintTransMotorMaxVel, 228 BSParam.LinkConstraintTransMotorMaxVel,
245 PhysicsScene.Params.linkConstraintTransMotorMaxForce); 229 BSParam.LinkConstraintTransMotorMaxForce);
246 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); 230 constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
247 if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) 231 if (BSParam.LinkConstraintSolverIterations != 0f)
248 { 232 {
249 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); 233 constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations);
250 } 234 }
251 return constrain; 235 return constrain;
252 } 236 }
@@ -260,14 +244,14 @@ public sealed class BSLinksetConstraints : BSLinkset
260 bool ret = false; 244 bool ret = false;
261 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", 245 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
262 rootPrim.LocalID, 246 rootPrim.LocalID,
263 rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), 247 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
264 childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X")); 248 childPrim.LocalID, childPrim.PhysBody.AddrString);
265 249
266 // Find the constraint for this link and get rid of it from the overall collection and from my list 250 // Find the constraint for this link and get rid of it from the overall collection and from my list
267 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) 251 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
268 { 252 {
269 // Make the child refresh its location 253 // Make the child refresh its location
270 BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr); 254 PhysicsScene.PE.PushUpdate(childPrim.PhysBody);
271 ret = true; 255 ret = true;
272 } 256 }
273 257
@@ -292,20 +276,17 @@ public sealed class BSLinksetConstraints : BSLinkset
292 private void RecomputeLinksetConstraints() 276 private void RecomputeLinksetConstraints()
293 { 277 {
294 float linksetMass = LinksetMass; 278 float linksetMass = LinksetMass;
295 LinksetRoot.UpdatePhysicalMassProperties(linksetMass); 279 LinksetRoot.UpdatePhysicalMassProperties(linksetMass, true);
296 280
297 // DEBUG: see of inter-linkset collisions are causing problems
298 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
299 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
300 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", 281 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}",
301 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); 282 LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass);
302 283
303 foreach (BSPhysObject child in m_children) 284 foreach (BSPhysObject child in m_children)
304 { 285 {
305 // A child in the linkset physically shows the mass of the whole linkset. 286 // A child in the linkset physically shows the mass of the whole linkset.
306 // This allows Bullet to apply enough force on the child to move the whole linkset. 287 // This allows Bullet to apply enough force on the child to move the whole linkset.
307 // (Also do the mass stuff before recomputing the constraint so mass is not zero.) 288 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
308 child.UpdatePhysicalMassProperties(linksetMass); 289 child.UpdatePhysicalMassProperties(linksetMass, true);
309 290
310 BSConstraint constrain; 291 BSConstraint constrain;
311 if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) 292 if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain))
@@ -315,11 +296,7 @@ public sealed class BSLinksetConstraints : BSLinkset
315 } 296 }
316 constrain.RecomputeConstraintVariables(linksetMass); 297 constrain.RecomputeConstraintVariables(linksetMass);
317 298
318 // DEBUG: see of inter-linkset collisions are causing problems 299 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
319 // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr,
320 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
321
322 // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG
323 } 300 }
324 301
325 } 302 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
new file mode 100755
index 0000000..92d62ff
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
@@ -0,0 +1,200 @@
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 System.Reflection;
31using Nini.Config;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35
36public struct MaterialAttributes
37{
38 // Material type values that correspond with definitions for LSL
39 public enum Material : int
40 {
41 Stone = 0,
42 Metal,
43 Glass,
44 Wood,
45 Flesh,
46 Plastic,
47 Rubber,
48 Light,
49 // Hereafter are BulletSim additions
50 Avatar,
51 NumberOfTypes // the count of types in the enum.
52 }
53
54 // Names must be in the order of the above enum.
55 // These names must coorespond to the lower case field names in the MaterialAttributes
56 // structure as reflection is used to select the field to put the value in.
57 public static readonly string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
58
59 public MaterialAttributes(string t, float d, float f, float r)
60 {
61 type = t;
62 density = d;
63 friction = f;
64 restitution = r;
65 }
66 public string type;
67 public float density;
68 public float friction;
69 public float restitution;
70}
71
72public static class BSMaterials
73{
74 // Attributes for each material type
75 private static readonly MaterialAttributes[] Attributes;
76
77 // Map of material name to material type code
78 public static readonly Dictionary<string, MaterialAttributes.Material> MaterialMap;
79
80 static BSMaterials()
81 {
82 // Attribute sets for both the non-physical and physical instances of materials.
83 Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2];
84
85 // Map of name to type code.
86 MaterialMap = new Dictionary<string, MaterialAttributes.Material>();
87 MaterialMap.Add("Stone", MaterialAttributes.Material.Stone);
88 MaterialMap.Add("Metal", MaterialAttributes.Material.Metal);
89 MaterialMap.Add("Glass", MaterialAttributes.Material.Glass);
90 MaterialMap.Add("Wood", MaterialAttributes.Material.Wood);
91 MaterialMap.Add("Flesh", MaterialAttributes.Material.Flesh);
92 MaterialMap.Add("Plastic", MaterialAttributes.Material.Plastic);
93 MaterialMap.Add("Rubber", MaterialAttributes.Material.Rubber);
94 MaterialMap.Add("Light", MaterialAttributes.Material.Light);
95 MaterialMap.Add("Avatar", MaterialAttributes.Material.Avatar);
96 }
97
98 // This is where all the default material attributes are defined.
99 public static void InitializeFromDefaults(ConfigurationParameters parms)
100 {
101 // Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL
102 float dDensity = parms.defaultDensity;
103 float dFriction = parms.defaultFriction;
104 float dRestitution = parms.defaultRestitution;
105 Attributes[(int)MaterialAttributes.Material.Stone] =
106 new MaterialAttributes("stone",dDensity, 0.8f, 0.4f);
107 Attributes[(int)MaterialAttributes.Material.Metal] =
108 new MaterialAttributes("metal",dDensity, 0.3f, 0.4f);
109 Attributes[(int)MaterialAttributes.Material.Glass] =
110 new MaterialAttributes("glass",dDensity, 0.2f, 0.7f);
111 Attributes[(int)MaterialAttributes.Material.Wood] =
112 new MaterialAttributes("wood",dDensity, 0.6f, 0.5f);
113 Attributes[(int)MaterialAttributes.Material.Flesh] =
114 new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f);
115 Attributes[(int)MaterialAttributes.Material.Plastic] =
116 new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f);
117 Attributes[(int)MaterialAttributes.Material.Rubber] =
118 new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f);
119 Attributes[(int)MaterialAttributes.Material.Light] =
120 new MaterialAttributes("light",dDensity, dFriction, dRestitution);
121 Attributes[(int)MaterialAttributes.Material.Avatar] =
122 new MaterialAttributes("avatar",3.5f, 0.2f, 0f);
123
124 Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
125 new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
126 Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
127 new MaterialAttributes("metalPhysical",dDensity, 0.3f, 0.4f);
128 Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
129 new MaterialAttributes("glassPhysical",dDensity, 0.2f, 0.7f);
130 Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
131 new MaterialAttributes("woodPhysical",dDensity, 0.6f, 0.5f);
132 Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
133 new MaterialAttributes("fleshPhysical",dDensity, 0.9f, 0.3f);
134 Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
135 new MaterialAttributes("plasticPhysical",dDensity, 0.4f, 0.7f);
136 Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
137 new MaterialAttributes("rubberPhysical",dDensity, 0.9f, 0.9f);
138 Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
139 new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
140 Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
141 new MaterialAttributes("avatarPhysical",3.5f, 0.2f, 0f);
142 }
143
144 // Under the [BulletSim] section, one can change the individual material
145 // attribute values. The format of the configuration parameter is:
146 // <materialName><Attribute>["Physical"] = floatValue
147 // For instance:
148 // [BulletSim]
149 // StoneFriction = 0.2
150 // FleshRestitutionPhysical = 0.8
151 // Materials can have different parameters for their static and
152 // physical instantiations. When setting the non-physical value,
153 // both values are changed. Setting the physical value only changes
154 // the physical value.
155 public static void InitializefromParameters(IConfig pConfig)
156 {
157 foreach (KeyValuePair<string, MaterialAttributes.Material> kvp in MaterialMap)
158 {
159 string matName = kvp.Key;
160 foreach (string attribName in MaterialAttributes.MaterialAttribs)
161 {
162 string paramName = matName + attribName;
163 if (pConfig.Contains(paramName))
164 {
165 float paramValue = pConfig.GetFloat(paramName);
166 SetAttributeValue((int)kvp.Value, attribName, paramValue);
167 // set the physical value also
168 SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
169 }
170 paramName += "Physical";
171 if (pConfig.Contains(paramName))
172 {
173 float paramValue = pConfig.GetFloat(paramName);
174 SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
175 }
176 }
177 }
178 }
179
180 // Use reflection to set the value in the attribute structure.
181 private static void SetAttributeValue(int matType, string attribName, float val)
182 {
183 MaterialAttributes thisAttrib = Attributes[matType];
184 FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower());
185 if (fieldInfo != null)
186 {
187 fieldInfo.SetValue(thisAttrib, val);
188 Attributes[matType] = thisAttrib;
189 }
190 }
191
192 // Given a material type, return a structure of attributes.
193 public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical)
194 {
195 int ind = (int)type;
196 if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
197 return Attributes[ind];
198 }
199}
200}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index bc6e4c4..9501e2d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -1,104 +1,486 @@
1using System; 1/*
2using System.Collections.Generic; 2 * Copyright (c) Contributors, http://opensimulator.org/
3using System.Text; 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4using OpenMetaverse; 4 *
5 5 * Redistribution and use in source and binary forms, with or without
6namespace OpenSim.Region.Physics.BulletSPlugin 6 * modification, are permitted provided that the following conditions are met:
7{ 7 * * Redistributions of source code must retain the above copyright
8public abstract class BSMotor 8 * notice, this list of conditions and the following disclaimer.
9{ 9 * * Redistributions in binary form must reproduce the above copyright
10 public virtual void Reset() { } 10 * notice, this list of conditions and the following disclaimer in the
11 public virtual void Zero() { } 11 * documentation and/or other materials provided with the distribution.
12} 12 * * Neither the name of the OpenSimulator Project nor the
13// Can all the incremental stepping be replaced with motor classes? 13 * names of its contributors may be used to endorse or promote products
14public class BSVMotor : BSMotor 14 * derived from this software without specific prior written permission.
15{ 15 *
16 public Vector3 FrameOfReference { get; set; } 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 public Vector3 Offset { get; set; } 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 public float TimeScale { get; set; } 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 public float TargetValueDecayTimeScale { get; set; } 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 public Vector3 CurrentValueReductionTimescale { get; set; } 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 public float Efficiency { get; set; } 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 public Vector3 TargetValue { get; private set; } 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 public Vector3 CurrentValue { get; private set; } 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 26 *
27 27 */
28 28using System;
29 BSVMotor(float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) 29using System.Collections.Generic;
30 { 30using System.Text;
31 TimeScale = timeScale; 31using OpenMetaverse;
32 TargetValueDecayTimeScale = decayTimeScale; 32using OpenSim.Framework;
33 CurrentValueReductionTimescale = frictionTimeScale; 33
34 Efficiency = efficiency; 34namespace OpenSim.Region.Physics.BulletSPlugin
35 } 35{
36 public void SetCurrent(Vector3 current) 36public abstract class BSMotor
37 { 37{
38 CurrentValue = current; 38 // Timescales and other things can be turned off by setting them to 'infinite'.
39 } 39 public const float Infinite = 12345.6f;
40 public void SetTarget(Vector3 target) 40 public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite);
41 { 41
42 TargetValue = target; 42 public BSMotor(string useName)
43 } 43 {
44 public Vector3 Step(float timeStep) 44 UseName = useName;
45 { 45 PhysicsScene = null;
46 if (CurrentValue.LengthSquared() > 0.001f) 46 Enabled = true;
47 { 47 }
48 // Vector3 origDir = Target; // DEBUG 48 public virtual bool Enabled { get; set; }
49 // Vector3 origVel = CurrentValue; // DEBUG 49 public virtual void Reset() { }
50 50 public virtual void Zero() { }
51 // Add (desiredVelocity - currentAppliedVelocity) / howLongItShouldTakeToComplete 51 public virtual void GenerateTestOutput(float timeStep) { }
52 Vector3 addAmount = (TargetValue - CurrentValue)/(TargetValue) * timeStep; 52
53 CurrentValue += addAmount; 53 // A name passed at motor creation for easily identifyable debugging messages.
54 54 public string UseName { get; private set; }
55 float decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep; 55
56 TargetValue *= (1f - decayFactor); 56 // Used only for outputting debug information. Might not be set so check for null.
57 57 public BSScene PhysicsScene { get; set; }
58 Vector3 frictionFactor = (Vector3.One / CurrentValueReductionTimescale) * timeStep; 58 protected void MDetailLog(string msg, params Object[] parms)
59 CurrentValue *= (Vector3.One - frictionFactor); 59 {
60 } 60 if (PhysicsScene != null)
61 else 61 {
62 { 62 PhysicsScene.DetailLog(msg, parms);
63 // if what remains of direction is very small, zero it. 63 }
64 TargetValue = Vector3.Zero; 64 }
65 CurrentValue = Vector3.Zero; 65}
66 66
67 // VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); 67// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
68 } 68// The TargetValue decays in TargetValueDecayTimeScale and
69 return CurrentValue; 69// the CurrentValue will be held back by FrictionTimeScale.
70 } 70// This motor will "zero itself" over time in that the targetValue will
71} 71// decay to zero and the currentValue will follow it to that zero.
72 72// The overall effect is for the returned correction value to go from large
73public class BSFMotor : BSMotor 73// values (the total difference between current and target minus friction)
74{ 74// to small and eventually zero values.
75 public float TimeScale { get; set; } 75// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay.
76 public float DecayTimeScale { get; set; } 76
77 public float Friction { get; set; } 77// For instance, if something is moving at speed X and the desired speed is Y,
78 public float Efficiency { get; set; } 78// CurrentValue is X and TargetValue is Y. As the motor is stepped, new
79 79// values of CurrentValue are returned that approach the TargetValue.
80 public float Target { get; private set; } 80// The feature of decaying TargetValue is so vehicles will eventually
81 public float CurrentValue { get; private set; } 81// come to a stop rather than run forever. This can be disabled by
82 82// setting TargetValueDecayTimescale to 'infinite'.
83 BSFMotor(float timeScale, float decayTimescale, float friction, float efficiency) 83// The change from CurrentValue to TargetValue is linear over TimeScale seconds.
84 { 84public class BSVMotor : BSMotor
85 } 85{
86 public void SetCurrent(float target) 86 // public Vector3 FrameOfReference { get; set; }
87 { 87 // public Vector3 Offset { get; set; }
88 } 88
89 public void SetTarget(float target) 89 public virtual float TimeScale { get; set; }
90 { 90 public virtual float TargetValueDecayTimeScale { get; set; }
91 } 91 public virtual Vector3 FrictionTimescale { get; set; }
92 public float Step(float timeStep) 92 public virtual float Efficiency { get; set; }
93 { 93
94 return 0f; 94 public virtual float ErrorZeroThreshold { get; set; }
95 } 95
96} 96 public virtual Vector3 TargetValue { get; protected set; }
97public class BSPIDMotor : BSMotor 97 public virtual Vector3 CurrentValue { get; protected set; }
98{ 98 public virtual Vector3 LastError { get; protected set; }
99 // TODO: write and use this one 99
100 BSPIDMotor() 100 public virtual bool ErrorIsZero()
101 { 101 {
102 } 102 return ErrorIsZero(LastError);
103} 103 }
104} 104 public virtual bool ErrorIsZero(Vector3 err)
105 {
106 return (err == Vector3.Zero || err.ApproxEquals(Vector3.Zero, ErrorZeroThreshold));
107 }
108
109 public BSVMotor(string useName)
110 : base(useName)
111 {
112 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
113 Efficiency = 1f;
114 FrictionTimescale = BSMotor.InfiniteVector;
115 CurrentValue = TargetValue = Vector3.Zero;
116 ErrorZeroThreshold = 0.001f;
117 }
118 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
119 : this(useName)
120 {
121 TimeScale = timeScale;
122 TargetValueDecayTimeScale = decayTimeScale;
123 FrictionTimescale = frictionTimeScale;
124 Efficiency = efficiency;
125 CurrentValue = TargetValue = Vector3.Zero;
126 }
127 public void SetCurrent(Vector3 current)
128 {
129 CurrentValue = current;
130 }
131 public void SetTarget(Vector3 target)
132 {
133 TargetValue = target;
134 }
135 public override void Zero()
136 {
137 base.Zero();
138 CurrentValue = TargetValue = Vector3.Zero;
139 }
140
141 // Compute the next step and return the new current value.
142 // Returns the correction needed to move 'current' to 'target'.
143 public virtual Vector3 Step(float timeStep)
144 {
145 if (!Enabled) return TargetValue;
146
147 Vector3 origTarget = TargetValue; // DEBUG
148 Vector3 origCurrVal = CurrentValue; // DEBUG
149
150 Vector3 correction = Vector3.Zero;
151 Vector3 error = TargetValue - CurrentValue;
152 LastError = error;
153 if (!ErrorIsZero(error))
154 {
155 correction = StepError(timeStep, error);
156
157 CurrentValue += correction;
158
159 // The desired value reduces to zero which also reduces the difference with current.
160 // If the decay time is infinite, don't decay at all.
161 float decayFactor = 0f;
162 if (TargetValueDecayTimeScale != BSMotor.Infinite)
163 {
164 decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep;
165 TargetValue *= (1f - decayFactor);
166 }
167
168 // The amount we can correct the error is reduced by the friction
169 Vector3 frictionFactor = Vector3.Zero;
170 if (FrictionTimescale != BSMotor.InfiniteVector)
171 {
172 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
173 // Individual friction components can be 'infinite' so compute each separately.
174 frictionFactor.X = (FrictionTimescale.X == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.X);
175 frictionFactor.Y = (FrictionTimescale.Y == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Y);
176 frictionFactor.Z = (FrictionTimescale.Z == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Z);
177 frictionFactor *= timeStep;
178 CurrentValue *= (Vector3.One - frictionFactor);
179 }
180
181 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
182 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
183 timeStep, error, correction);
184 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}",
185 BSScene.DetailLogZero, UseName,
186 TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
187 TargetValue, CurrentValue);
188 }
189 else
190 {
191 // Difference between what we have and target is small. Motor is done.
192 if (TargetValue.ApproxEquals(Vector3.Zero, ErrorZeroThreshold))
193 {
194 // The target can step down to nearly zero but not get there. If close to zero
195 // it is really zero.
196 TargetValue = Vector3.Zero;
197 }
198 CurrentValue = TargetValue;
199 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},currTgt={4},currCurr={5}",
200 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, TargetValue, CurrentValue);
201 }
202
203 return correction;
204 }
205 // version of step that sets the current value before doing the step
206 public virtual Vector3 Step(float timeStep, Vector3 current)
207 {
208 CurrentValue = current;
209 return Step(timeStep);
210 }
211 public virtual Vector3 StepError(float timeStep, Vector3 error)
212 {
213 if (!Enabled) return Vector3.Zero;
214
215 Vector3 returnCorrection = Vector3.Zero;
216 if (!ErrorIsZero(error))
217 {
218 // correction = error / secondsItShouldTakeToCorrect
219 Vector3 correctionAmount;
220 if (TimeScale == 0f || TimeScale == BSMotor.Infinite)
221 correctionAmount = error * timeStep;
222 else
223 correctionAmount = error / TimeScale * timeStep;
224
225 returnCorrection = correctionAmount;
226 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},timeStep={2},timeScale={3},err={4},corr={5}",
227 BSScene.DetailLogZero, UseName, timeStep, TimeScale, error, correctionAmount);
228 }
229 return returnCorrection;
230 }
231
232 // The user sets all the parameters and calls this which outputs values until error is zero.
233 public override void GenerateTestOutput(float timeStep)
234 {
235 // maximum number of outputs to generate.
236 int maxOutput = 50;
237 MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName);
238 MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}",
239 BSScene.DetailLogZero, UseName,
240 TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency,
241 CurrentValue, TargetValue);
242
243 LastError = BSMotor.InfiniteVector;
244 while (maxOutput-- > 0 && !LastError.ApproxEquals(Vector3.Zero, ErrorZeroThreshold))
245 {
246 Vector3 lastStep = Step(timeStep);
247 MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}",
248 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep);
249 }
250 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName);
251
252
253 }
254
255 public override string ToString()
256 {
257 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>",
258 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale);
259 }
260}
261
262// ============================================================================
263// ============================================================================
264public class BSFMotor : BSMotor
265{
266 public virtual float TimeScale { get; set; }
267 public virtual float TargetValueDecayTimeScale { get; set; }
268 public virtual float FrictionTimescale { get; set; }
269 public virtual float Efficiency { get; set; }
270
271 public virtual float ErrorZeroThreshold { get; set; }
272
273 public virtual float TargetValue { get; protected set; }
274 public virtual float CurrentValue { get; protected set; }
275 public virtual float LastError { get; protected set; }
276
277 public virtual bool ErrorIsZero()
278 {
279 return ErrorIsZero(LastError);
280 }
281 public virtual bool ErrorIsZero(float err)
282 {
283 return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold);
284 }
285
286 public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency)
287 : base(useName)
288 {
289 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
290 Efficiency = 1f;
291 FrictionTimescale = BSMotor.Infinite;
292 CurrentValue = TargetValue = 0f;
293 ErrorZeroThreshold = 0.01f;
294 }
295 public void SetCurrent(float current)
296 {
297 CurrentValue = current;
298 }
299 public void SetTarget(float target)
300 {
301 TargetValue = target;
302 }
303 public override void Zero()
304 {
305 base.Zero();
306 CurrentValue = TargetValue = 0f;
307 }
308
309 public virtual float Step(float timeStep)
310 {
311 if (!Enabled) return TargetValue;
312
313 float origTarget = TargetValue; // DEBUG
314 float origCurrVal = CurrentValue; // DEBUG
315
316 float correction = 0f;
317 float error = TargetValue - CurrentValue;
318 LastError = error;
319 if (!ErrorIsZero(error))
320 {
321 correction = StepError(timeStep, error);
322
323 CurrentValue += correction;
324
325 // The desired value reduces to zero which also reduces the difference with current.
326 // If the decay time is infinite, don't decay at all.
327 float decayFactor = 0f;
328 if (TargetValueDecayTimeScale != BSMotor.Infinite)
329 {
330 decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep;
331 TargetValue *= (1f - decayFactor);
332 }
333
334 // The amount we can correct the error is reduced by the friction
335 float frictionFactor = 0f;
336 if (FrictionTimescale != BSMotor.Infinite)
337 {
338 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
339 // Individual friction components can be 'infinite' so compute each separately.
340 frictionFactor = 1f / FrictionTimescale;
341 frictionFactor *= timeStep;
342 CurrentValue *= (1f - frictionFactor);
343 }
344
345 MDetailLog("{0}, BSFMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
346 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
347 timeStep, error, correction);
348 MDetailLog("{0}, BSFMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}",
349 BSScene.DetailLogZero, UseName,
350 TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
351 TargetValue, CurrentValue);
352 }
353 else
354 {
355 // Difference between what we have and target is small. Motor is done.
356 if (Util.InRange<float>(TargetValue, -ErrorZeroThreshold, ErrorZeroThreshold))
357 {
358 // The target can step down to nearly zero but not get there. If close to zero
359 // it is really zero.
360 TargetValue = 0f;
361 }
362 CurrentValue = TargetValue;
363 MDetailLog("{0}, BSFMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}",
364 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue);
365 }
366
367 return CurrentValue;
368 }
369
370 public virtual float StepError(float timeStep, float error)
371 {
372 if (!Enabled) return 0f;
373
374 float returnCorrection = 0f;
375 if (!ErrorIsZero(error))
376 {
377 // correction = error / secondsItShouldTakeToCorrect
378 float correctionAmount;
379 if (TimeScale == 0f || TimeScale == BSMotor.Infinite)
380 correctionAmount = error * timeStep;
381 else
382 correctionAmount = error / TimeScale * timeStep;
383
384 returnCorrection = correctionAmount;
385 MDetailLog("{0}, BSFMotor.Step,nonZero,{1},timeStep={2},timeScale={3},err={4},corr={5}",
386 BSScene.DetailLogZero, UseName, timeStep, TimeScale, error, correctionAmount);
387 }
388 return returnCorrection;
389 }
390
391 public override string ToString()
392 {
393 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>",
394 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale);
395 }
396
397}
398
399// ============================================================================
400// ============================================================================
401// Proportional, Integral, Derivitive Motor
402// Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors.
403public class BSPIDVMotor : BSVMotor
404{
405 // Larger makes more overshoot, smaller means converge quicker. Range of 0.1 to 10.
406 public Vector3 proportionFactor { get; set; }
407 public Vector3 integralFactor { get; set; }
408 public Vector3 derivFactor { get; set; }
409
410 // The factors are vectors for the three dimensions. This is the proportional of each
411 // that is applied. This could be multiplied through the actual factors but it
412 // is sometimes easier to manipulate the factors and their mix separately.
413 // to
414 public Vector3 FactorMix;
415
416 // Arbritrary factor range.
417 // EfficiencyHigh means move quickly to the correct number. EfficiencyLow means might over correct.
418 public float EfficiencyHigh = 0.4f;
419 public float EfficiencyLow = 4.0f;
420
421 // Running integration of the error
422 Vector3 RunningIntegration { get; set; }
423
424 public BSPIDVMotor(string useName)
425 : base(useName)
426 {
427 proportionFactor = new Vector3(1.00f, 1.00f, 1.00f);
428 integralFactor = new Vector3(1.00f, 1.00f, 1.00f);
429 derivFactor = new Vector3(1.00f, 1.00f, 1.00f);
430 FactorMix = new Vector3(0.5f, 0.25f, 0.25f);
431 RunningIntegration = Vector3.Zero;
432 LastError = Vector3.Zero;
433 }
434
435 public override void Zero()
436 {
437 base.Zero();
438 }
439
440 public override float Efficiency
441 {
442 get { return base.Efficiency; }
443 set
444 {
445 base.Efficiency = Util.Clamp(value, 0f, 1f);
446
447 // Compute factors based on efficiency.
448 // If efficiency is high (1f), use a factor value that moves the error value to zero with little overshoot.
449 // If efficiency is low (0f), use a factor value that overcorrects.
450 // TODO: might want to vary contribution of different factor depending on efficiency.
451 float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f;
452 // float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow;
453
454 proportionFactor = new Vector3(factor, factor, factor);
455 integralFactor = new Vector3(factor, factor, factor);
456 derivFactor = new Vector3(factor, factor, factor);
457
458 MDetailLog("{0},BSPIDVMotor.setEfficiency,eff={1},factor={2}", BSScene.DetailLogZero, Efficiency, factor);
459 }
460 }
461
462 // Advance the PID computation on this error.
463 public override Vector3 StepError(float timeStep, Vector3 error)
464 {
465 if (!Enabled) return Vector3.Zero;
466
467 // Add up the error so we can integrate over the accumulated errors
468 RunningIntegration += error * timeStep;
469
470 // A simple derivitive is the rate of change from the last error.
471 Vector3 derivitive = (error - LastError) * timeStep;
472 LastError = error;
473
474 // Correction = (proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError)
475 Vector3 ret = error * timeStep * proportionFactor * FactorMix.X
476 + RunningIntegration * integralFactor * FactorMix.Y
477 + derivitive * derivFactor * FactorMix.Z
478 ;
479
480 MDetailLog("{0},BSPIDVMotor.step,ts={1},err={2},runnInt={3},deriv={4},ret={5}",
481 BSScene.DetailLogZero, timeStep, error, RunningIntegration, derivitive, ret);
482
483 return ret;
484 }
485}
486}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
new file mode 100755
index 0000000..601c78c
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -0,0 +1,725 @@
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.Region.Physics.Manager;
32
33using OpenMetaverse;
34using Nini.Config;
35
36namespace OpenSim.Region.Physics.BulletSPlugin
37{
38public static class BSParam
39{
40 // Level of Detail values kept as float because that's what the Meshmerizer wants
41 public static float MeshLOD { get; private set; }
42 public static float MeshCircularLOD { get; private set; }
43 public static float MeshMegaPrimLOD { get; private set; }
44 public static float MeshMegaPrimThreshold { get; private set; }
45 public static float SculptLOD { get; private set; }
46
47 public static float MinimumObjectMass { get; private set; }
48 public static float MaximumObjectMass { get; private set; }
49 public static float MaxLinearVelocity { get; private set; }
50 public static float MaxAngularVelocity { get; private set; }
51 public static float MaxAddForceMagnitude { get; private set; }
52
53 public static float LinearDamping { get; private set; }
54 public static float AngularDamping { get; private set; }
55 public static float DeactivationTime { get; private set; }
56 public static float LinearSleepingThreshold { get; private set; }
57 public static float AngularSleepingThreshold { get; private set; }
58 public static float CcdMotionThreshold { get; private set; }
59 public static float CcdSweptSphereRadius { get; private set; }
60 public static float ContactProcessingThreshold { get; private set; }
61
62 public static bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
63 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
64 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
65 public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
66
67 public static float TerrainImplementation { get; private set; }
68 public static float TerrainFriction { get; private set; }
69 public static float TerrainHitFraction { get; private set; }
70 public static float TerrainRestitution { get; private set; }
71 public static float TerrainCollisionMargin { get; private set; }
72
73 public static float DefaultFriction;
74 public static float DefaultDensity;
75 public static float DefaultRestitution;
76 public static float CollisionMargin;
77 public static float Gravity;
78
79 // Physics Engine operation
80 public static float MaxPersistantManifoldPoolSize;
81 public static float MaxCollisionAlgorithmPoolSize;
82 public static float ShouldDisableContactPoolDynamicAllocation;
83 public static float ShouldForceUpdateAllAabbs;
84 public static float ShouldRandomizeSolverOrder;
85 public static float ShouldSplitSimulationIslands;
86 public static float ShouldEnableFrictionCaching;
87 public static float NumberOfSolverIterations;
88 public static bool UseSingleSidedMeshes { get { return UseSingleSidedMeshesF != ConfigurationParameters.numericFalse; } }
89 public static float UseSingleSidedMeshesF;
90
91 // Avatar parameters
92 public static float AvatarFriction { get; private set; }
93 public static float AvatarStandingFriction { get; private set; }
94 public static float AvatarAlwaysRunFactor { get; private set; }
95 public static float AvatarDensity { get; private set; }
96 public static float AvatarRestitution { get; private set; }
97 public static float AvatarCapsuleWidth { get; private set; }
98 public static float AvatarCapsuleDepth { get; private set; }
99 public static float AvatarCapsuleHeight { get; private set; }
100 public static float AvatarContactProcessingThreshold { get; private set; }
101 public static float AvatarStepHeight { get; private set; }
102 public static float AvatarStepApproachFactor { get; private set; }
103 public static float AvatarStepForceFactor { get; private set; }
104
105 // Vehicle parameters
106 public static float VehicleMaxLinearVelocity { get; private set; }
107 public static float VehicleMaxLinearVelocitySq { get; private set; }
108 public static float VehicleMaxAngularVelocity { get; private set; }
109 public static float VehicleMaxAngularVelocitySq { get; private set; }
110 public static float VehicleAngularDamping { get; private set; }
111 public static float VehicleFriction { get; private set; }
112 public static float VehicleRestitution { get; private set; }
113 public static float VehicleLinearFactor { get; private set; }
114 public static Vector3 VehicleLinearFactorV { get; private set; }
115 public static float VehicleAngularFactor { get; private set; }
116 public static Vector3 VehicleAngularFactorV { get; private set; }
117 public static float VehicleGroundGravityFudge { get; private set; }
118 public static float VehicleDebuggingEnabled { get; private set; }
119
120 public static float LinksetImplementation { get; private set; }
121 public static float LinkConstraintUseFrameOffset { get; private set; }
122 public static float LinkConstraintEnableTransMotor { get; private set; }
123 public static float LinkConstraintTransMotorMaxVel { get; private set; }
124 public static float LinkConstraintTransMotorMaxForce { get; private set; }
125 public static float LinkConstraintERP { get; private set; }
126 public static float LinkConstraintCFM { get; private set; }
127 public static float LinkConstraintSolverIterations { get; private set; }
128
129 public static float PID_D { get; private set; } // derivative
130 public static float PID_P { get; private set; } // proportional
131
132 // Various constants that come from that other virtual world that shall not be named.
133 public const float MinGravityZ = -1f;
134 public const float MaxGravityZ = 28f;
135 public const float MinFriction = 0f;
136 public const float MaxFriction = 255f;
137 public const float MinDensity = 0.01f;
138 public const float MaxDensity = 22587f;
139 public const float MinRestitution = 0f;
140 public const float MaxRestitution = 1f;
141
142 // ===========================================================================
143 public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
144 public delegate float ParamGet(BSScene scene);
145 public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
146 public delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
147
148 public struct ParameterDefn
149 {
150 public string name; // string name of the parameter
151 public string desc; // a short description of what the parameter means
152 public float defaultValue; // default value if not specified anywhere else
153 public ParamUser userParam; // get the value from the configuration file
154 public ParamGet getter; // return the current value stored for this parameter
155 public ParamSet setter; // set the current value for this parameter
156 public SetOnObject onObject; // set the value on an object in the physical domain
157 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
158 {
159 name = n;
160 desc = d;
161 defaultValue = v;
162 userParam = u;
163 getter = g;
164 setter = s;
165 onObject = null;
166 }
167 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
168 {
169 name = n;
170 desc = d;
171 defaultValue = v;
172 userParam = u;
173 getter = g;
174 setter = s;
175 onObject = o;
176 }
177 }
178
179 // List of all of the externally visible parameters.
180 // For each parameter, this table maps a text name to getter and setters.
181 // To add a new externally referencable/settable parameter, add the paramter storage
182 // location somewhere in the program and make an entry in this table with the
183 // getters and setters.
184 // It is easiest to find an existing definition and copy it.
185 // Parameter values are floats. Booleans are converted to a floating value.
186 //
187 // A ParameterDefn() takes the following parameters:
188 // -- the text name of the parameter. This is used for console input and ini file.
189 // -- a short text description of the parameter. This shows up in the console listing.
190 // -- a default value (float)
191 // -- a delegate for fetching the parameter from the ini file.
192 // Should handle fetching the right type from the ini file and converting it.
193 // -- a delegate for getting the value as a float
194 // -- a delegate for setting the value from a float
195 // -- an optional delegate to update the value in the world. Most often used to
196 // push the new value to an in-world object.
197 //
198 // The single letter parameters for the delegates are:
199 // s = BSScene
200 // o = BSPhysObject
201 // p = string parameter name
202 // l = localID of referenced object
203 // v = value (float)
204 // cf = parameter configuration class (for fetching values from ini file)
205 private static ParameterDefn[] ParameterDefinitions =
206 {
207 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
208 ConfigurationParameters.numericTrue,
209 (s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
210 (s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); },
211 (s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ),
212 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
213 ConfigurationParameters.numericFalse,
214 (s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
215 (s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); },
216 (s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ),
217 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
218 ConfigurationParameters.numericTrue,
219 (s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
220 (s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); },
221 (s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ),
222 new ParameterDefn("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
223 ConfigurationParameters.numericTrue,
224 (s,cf,p,v) => { ShouldRemoveZeroWidthTriangles = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
225 (s) => { return BSParam.NumericBool(ShouldRemoveZeroWidthTriangles); },
226 (s,p,l,v) => { ShouldRemoveZeroWidthTriangles = BSParam.BoolNumeric(v); } ),
227
228 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
229 32f,
230 (s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); },
231 (s) => { return MeshLOD; },
232 (s,p,l,v) => { MeshLOD = v; } ),
233 new ParameterDefn("MeshLevelOfDetailCircular", "Level of detail for prims with circular cuts or shapes",
234 32f,
235 (s,cf,p,v) => { MeshCircularLOD = (float)cf.GetInt(p, (int)v); },
236 (s) => { return MeshCircularLOD; },
237 (s,p,l,v) => { MeshCircularLOD = v; } ),
238 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
239 10f,
240 (s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
241 (s) => { return MeshMegaPrimThreshold; },
242 (s,p,l,v) => { MeshMegaPrimThreshold = v; } ),
243 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
244 32f,
245 (s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
246 (s) => { return MeshMegaPrimLOD; },
247 (s,p,l,v) => { MeshMegaPrimLOD = v; } ),
248 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
249 32f,
250 (s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); },
251 (s) => { return SculptLOD; },
252 (s,p,l,v) => { SculptLOD = v; } ),
253
254 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
255 10f,
256 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
257 (s) => { return (float)s.m_maxSubSteps; },
258 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
259 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
260 1f / 60f,
261 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
262 (s) => { return (float)s.m_fixedTimeStep; },
263 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
264 new ParameterDefn("NominalFrameRate", "The base frame rate we claim",
265 55f,
266 (s,cf,p,v) => { s.NominalFrameRate = cf.GetInt(p, (int)v); },
267 (s) => { return (float)s.NominalFrameRate; },
268 (s,p,l,v) => { s.NominalFrameRate = (int)v; } ),
269 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
270 2048f,
271 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
272 (s) => { return (float)s.m_maxCollisionsPerFrame; },
273 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
274 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
275 8000f,
276 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
277 (s) => { return (float)s.m_maxUpdatesPerFrame; },
278 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
279
280 new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)",
281 0.0001f,
282 (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
283 (s) => { return (float)MinimumObjectMass; },
284 (s,p,l,v) => { MinimumObjectMass = v; } ),
285 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
286 10000.01f,
287 (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
288 (s) => { return (float)MaximumObjectMass; },
289 (s,p,l,v) => { MaximumObjectMass = v; } ),
290 new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
291 1000.0f,
292 (s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); },
293 (s) => { return (float)MaxLinearVelocity; },
294 (s,p,l,v) => { MaxLinearVelocity = v; } ),
295 new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
296 1000.0f,
297 (s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); },
298 (s) => { return (float)MaxAngularVelocity; },
299 (s,p,l,v) => { MaxAngularVelocity = v; } ),
300 // LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject
301 new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)",
302 20000.0f,
303 (s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); },
304 (s) => { return (float)MaxAddForceMagnitude; },
305 (s,p,l,v) => { MaxAddForceMagnitude = v; } ),
306
307 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
308 2200f,
309 (s,cf,p,v) => { PID_D = cf.GetFloat(p, v); },
310 (s) => { return (float)PID_D; },
311 (s,p,l,v) => { PID_D = v; } ),
312 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
313 900f,
314 (s,cf,p,v) => { PID_P = cf.GetFloat(p, v); },
315 (s) => { return (float)PID_P; },
316 (s,p,l,v) => { PID_P = v; } ),
317
318 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
319 0.2f,
320 (s,cf,p,v) => { DefaultFriction = cf.GetFloat(p, v); },
321 (s) => { return DefaultFriction; },
322 (s,p,l,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
323 new ParameterDefn("DefaultDensity", "Density for new objects" ,
324 10.000006836f, // Aluminum g/cm3
325 (s,cf,p,v) => { DefaultDensity = cf.GetFloat(p, v); },
326 (s) => { return DefaultDensity; },
327 (s,p,l,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
328 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
329 0f,
330 (s,cf,p,v) => { DefaultRestitution = cf.GetFloat(p, v); },
331 (s) => { return DefaultRestitution; },
332 (s,p,l,v) => { DefaultRestitution = v; s.UnmanagedParams[0].defaultRestitution = v; } ),
333 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
334 0.04f,
335 (s,cf,p,v) => { CollisionMargin = cf.GetFloat(p, v); },
336 (s) => { return CollisionMargin; },
337 (s,p,l,v) => { CollisionMargin = v; s.UnmanagedParams[0].collisionMargin = v; } ),
338 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
339 -9.80665f,
340 (s,cf,p,v) => { Gravity = cf.GetFloat(p, v); },
341 (s) => { return Gravity; },
342 (s,p,l,v) => { Gravity = v; s.UnmanagedParams[0].gravity = v; },
343 (s,o,v) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,v)); } ),
344
345
346 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
347 0f,
348 (s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); },
349 (s) => { return LinearDamping; },
350 (s,p,l,v) => { LinearDamping = v; },
351 (s,o,v) => { s.PE.SetDamping(o.PhysBody, v, AngularDamping); } ),
352 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
353 0f,
354 (s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); },
355 (s) => { return AngularDamping; },
356 (s,p,l,v) => { AngularDamping = v; },
357 (s,o,v) => { s.PE.SetDamping(o.PhysBody, LinearDamping, v); } ),
358 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
359 0.2f,
360 (s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); },
361 (s) => { return DeactivationTime; },
362 (s,p,l,v) => { DeactivationTime = v; },
363 (s,o,v) => { s.PE.SetDeactivationTime(o.PhysBody, v); } ),
364 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
365 0.8f,
366 (s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); },
367 (s) => { return LinearSleepingThreshold; },
368 (s,p,l,v) => { LinearSleepingThreshold = v;},
369 (s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ),
370 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
371 1.0f,
372 (s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); },
373 (s) => { return AngularSleepingThreshold; },
374 (s,p,l,v) => { AngularSleepingThreshold = v;},
375 (s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ),
376 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
377 0.0f, // set to zero to disable
378 (s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); },
379 (s) => { return CcdMotionThreshold; },
380 (s,p,l,v) => { CcdMotionThreshold = v;},
381 (s,o,v) => { s.PE.SetCcdMotionThreshold(o.PhysBody, v); } ),
382 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
383 0.2f,
384 (s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); },
385 (s) => { return CcdSweptSphereRadius; },
386 (s,p,l,v) => { CcdSweptSphereRadius = v;},
387 (s,o,v) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, v); } ),
388 new ParameterDefn("ContactProcessingThreshold", "Distance above which contacts can be discarded (0 means no discard)" ,
389 0.0f,
390 (s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); },
391 (s) => { return ContactProcessingThreshold; },
392 (s,p,l,v) => { ContactProcessingThreshold = v;},
393 (s,o,v) => { s.PE.SetContactProcessingThreshold(o.PhysBody, v); } ),
394
395 new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
396 (float)BSTerrainPhys.TerrainImplementation.Mesh,
397 (s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); },
398 (s) => { return TerrainImplementation; },
399 (s,p,l,v) => { TerrainImplementation = v; } ),
400 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
401 0.3f,
402 (s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); },
403 (s) => { return TerrainFriction; },
404 (s,p,l,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
405 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
406 0.8f,
407 (s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); },
408 (s) => { return TerrainHitFraction; },
409 (s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
410 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
411 0f,
412 (s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); },
413 (s) => { return TerrainRestitution; },
414 (s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
415 new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
416 0.08f,
417 (s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); },
418 (s) => { return TerrainCollisionMargin; },
419 (s,p,l,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
420
421 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
422 0.2f,
423 (s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); },
424 (s) => { return AvatarFriction; },
425 (s,p,l,v) => { AvatarFriction = v; } ),
426 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
427 10.0f,
428 (s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); },
429 (s) => { return AvatarStandingFriction; },
430 (s,p,l,v) => { AvatarStandingFriction = v; } ),
431 new ParameterDefn("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
432 1.3f,
433 (s,cf,p,v) => { AvatarAlwaysRunFactor = cf.GetFloat(p, v); },
434 (s) => { return AvatarAlwaysRunFactor; },
435 (s,p,l,v) => { AvatarAlwaysRunFactor = v; } ),
436 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
437 3.5f,
438 (s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
439 (s) => { return AvatarDensity; },
440 (s,p,l,v) => { AvatarDensity = v; } ),
441 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
442 0f,
443 (s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); },
444 (s) => { return AvatarRestitution; },
445 (s,p,l,v) => { AvatarRestitution = v; } ),
446 new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
447 0.6f,
448 (s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); },
449 (s) => { return AvatarCapsuleWidth; },
450 (s,p,l,v) => { AvatarCapsuleWidth = v; } ),
451 new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
452 0.45f,
453 (s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); },
454 (s) => { return AvatarCapsuleDepth; },
455 (s,p,l,v) => { AvatarCapsuleDepth = v; } ),
456 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
457 1.5f,
458 (s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); },
459 (s) => { return AvatarCapsuleHeight; },
460 (s,p,l,v) => { AvatarCapsuleHeight = v; } ),
461 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
462 0.1f,
463 (s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); },
464 (s) => { return AvatarContactProcessingThreshold; },
465 (s,p,l,v) => { AvatarContactProcessingThreshold = v; } ),
466 new ParameterDefn("AvatarStepHeight", "Height of a step obstacle to consider step correction",
467 0.3f,
468 (s,cf,p,v) => { AvatarStepHeight = cf.GetFloat(p, v); },
469 (s) => { return AvatarStepHeight; },
470 (s,p,l,v) => { AvatarStepHeight = v; } ),
471 new ParameterDefn("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
472 0.6f,
473 (s,cf,p,v) => { AvatarStepApproachFactor = cf.GetFloat(p, v); },
474 (s) => { return AvatarStepApproachFactor; },
475 (s,p,l,v) => { AvatarStepApproachFactor = v; } ),
476 new ParameterDefn("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
477 2.0f,
478 (s,cf,p,v) => { AvatarStepForceFactor = cf.GetFloat(p, v); },
479 (s) => { return AvatarStepForceFactor; },
480 (s,p,l,v) => { AvatarStepForceFactor = v; } ),
481
482 new ParameterDefn("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
483 1000.0f,
484 (s,cf,p,v) => { VehicleMaxLinearVelocity = cf.GetFloat(p, v); },
485 (s) => { return (float)VehicleMaxLinearVelocity; },
486 (s,p,l,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySq = v * v; } ),
487 new ParameterDefn("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle",
488 12.0f,
489 (s,cf,p,v) => { VehicleMaxAngularVelocity = cf.GetFloat(p, v); },
490 (s) => { return (float)VehicleMaxAngularVelocity; },
491 (s,p,l,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
492 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
493 0.0f,
494 (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
495 (s) => { return VehicleAngularDamping; },
496 (s,p,l,v) => { VehicleAngularDamping = v; } ),
497 new ParameterDefn("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (0.0 - 1.0)",
498 1.0f,
499 (s,cf,p,v) => { VehicleLinearFactor = cf.GetFloat(p, v); },
500 (s) => { return VehicleLinearFactor; },
501 (s,p,l,v) => { VehicleLinearFactor = v; VehicleLinearFactorV = new Vector3(v, v, v); } ),
502 new ParameterDefn("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (0.0 - 1.0)",
503 1.0f,
504 (s,cf,p,v) => { VehicleAngularFactor = cf.GetFloat(p, v); },
505 (s) => { return VehicleAngularFactor; },
506 (s,p,l,v) => { VehicleAngularFactor = v; VehicleAngularFactorV = new Vector3(v, v, v); } ),
507 new ParameterDefn("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
508 0.0f,
509 (s,cf,p,v) => { VehicleFriction = cf.GetFloat(p, v); },
510 (s) => { return VehicleFriction; },
511 (s,p,l,v) => { VehicleFriction = v; } ),
512 new ParameterDefn("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
513 0.0f,
514 (s,cf,p,v) => { VehicleRestitution = cf.GetFloat(p, v); },
515 (s) => { return VehicleRestitution; },
516 (s,p,l,v) => { VehicleRestitution = v; } ),
517 new ParameterDefn("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
518 0.2f,
519 (s,cf,p,v) => { VehicleGroundGravityFudge = cf.GetFloat(p, v); },
520 (s) => { return VehicleGroundGravityFudge; },
521 (s,p,l,v) => { VehicleGroundGravityFudge = v; } ),
522 new ParameterDefn("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
523 ConfigurationParameters.numericFalse,
524 (s,cf,p,v) => { VehicleDebuggingEnabled = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
525 (s) => { return VehicleDebuggingEnabled; },
526 (s,p,l,v) => { VehicleDebuggingEnabled = v; } ),
527
528 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
529 0f,
530 (s,cf,p,v) => { MaxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
531 (s) => { return MaxPersistantManifoldPoolSize; },
532 (s,p,l,v) => { MaxPersistantManifoldPoolSize = v; s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
533 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
534 0f,
535 (s,cf,p,v) => { MaxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
536 (s) => { return MaxCollisionAlgorithmPoolSize; },
537 (s,p,l,v) => { MaxCollisionAlgorithmPoolSize = v; s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
538 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
539 ConfigurationParameters.numericFalse,
540 (s,cf,p,v) => { ShouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
541 (s) => { return ShouldDisableContactPoolDynamicAllocation; },
542 (s,p,l,v) => { ShouldDisableContactPoolDynamicAllocation = v; s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ),
543 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
544 ConfigurationParameters.numericFalse,
545 (s,cf,p,v) => { ShouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
546 (s) => { return ShouldForceUpdateAllAabbs; },
547 (s,p,l,v) => { ShouldForceUpdateAllAabbs = v; s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ),
548 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
549 ConfigurationParameters.numericTrue,
550 (s,cf,p,v) => { ShouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
551 (s) => { return ShouldRandomizeSolverOrder; },
552 (s,p,l,v) => { ShouldRandomizeSolverOrder = v; s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ),
553 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
554 ConfigurationParameters.numericTrue,
555 (s,cf,p,v) => { ShouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
556 (s) => { return ShouldSplitSimulationIslands; },
557 (s,p,l,v) => { ShouldSplitSimulationIslands = v; s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ),
558 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
559 ConfigurationParameters.numericTrue,
560 (s,cf,p,v) => { ShouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
561 (s) => { return ShouldEnableFrictionCaching; },
562 (s,p,l,v) => { ShouldEnableFrictionCaching = v; s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ),
563 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
564 0f, // zero says use Bullet default
565 (s,cf,p,v) => { NumberOfSolverIterations = cf.GetFloat(p, v); },
566 (s) => { return NumberOfSolverIterations; },
567 (s,p,l,v) => { NumberOfSolverIterations = v; s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
568 new ParameterDefn("UseSingleSidedMeshes", "Whether to compute collisions based on single sided meshes.",
569 ConfigurationParameters.numericTrue,
570 (s,cf,p,v) => { UseSingleSidedMeshesF = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
571 (s) => { return UseSingleSidedMeshesF; },
572 (s,p,l,v) => { UseSingleSidedMeshesF = v; s.UnmanagedParams[0].useSingleSidedMeshes = v; } ),
573
574 new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
575 (float)BSLinkset.LinksetImplementation.Compound,
576 (s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); },
577 (s) => { return LinksetImplementation; },
578 (s,p,l,v) => { LinksetImplementation = v; } ),
579 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
580 ConfigurationParameters.numericFalse,
581 (s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
582 (s) => { return LinkConstraintUseFrameOffset; },
583 (s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ),
584 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
585 ConfigurationParameters.numericTrue,
586 (s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
587 (s) => { return LinkConstraintEnableTransMotor; },
588 (s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ),
589 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
590 5.0f,
591 (s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
592 (s) => { return LinkConstraintTransMotorMaxVel; },
593 (s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ),
594 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
595 0.1f,
596 (s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
597 (s) => { return LinkConstraintTransMotorMaxForce; },
598 (s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ),
599 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
600 0.1f,
601 (s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); },
602 (s) => { return LinkConstraintCFM; },
603 (s,p,l,v) => { LinkConstraintCFM = v; } ),
604 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
605 0.1f,
606 (s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); },
607 (s) => { return LinkConstraintERP; },
608 (s,p,l,v) => { LinkConstraintERP = v; } ),
609 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
610 40,
611 (s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); },
612 (s) => { return LinkConstraintSolverIterations; },
613 (s,p,l,v) => { LinkConstraintSolverIterations = v; } ),
614
615 new ParameterDefn("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)",
616 0f,
617 (s,cf,p,v) => { s.PhysicsMetricDumpFrames = cf.GetFloat(p, (int)v); },
618 (s) => { return (float)s.PhysicsMetricDumpFrames; },
619 (s,p,l,v) => { s.PhysicsMetricDumpFrames = (int)v; } ),
620 new ParameterDefn("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool",
621 0f,
622 (s,cf,p,v) => { ; },
623 (s) => { return 0f; },
624 (s,p,l,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ),
625 new ParameterDefn("ResetConstraintSolver", "Setting this is any value resets the constraint solver",
626 0f,
627 (s,cf,p,v) => { ; },
628 (s) => { return 0f; },
629 (s,p,l,v) => { BSParam.ResetConstraintSolverTainted(s, v); } ),
630 };
631
632 // Convert a boolean to our numeric true and false values
633 public static float NumericBool(bool b)
634 {
635 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
636 }
637
638 // Convert numeric true and false values to a boolean
639 public static bool BoolNumeric(float b)
640 {
641 return (b == ConfigurationParameters.numericTrue ? true : false);
642 }
643
644 // Search through the parameter definitions and return the matching
645 // ParameterDefn structure.
646 // Case does not matter as names are compared after converting to lower case.
647 // Returns 'false' if the parameter is not found.
648 internal static bool TryGetParameter(string paramName, out ParameterDefn defn)
649 {
650 bool ret = false;
651 ParameterDefn foundDefn = new ParameterDefn();
652 string pName = paramName.ToLower();
653
654 foreach (ParameterDefn parm in ParameterDefinitions)
655 {
656 if (pName == parm.name.ToLower())
657 {
658 foundDefn = parm;
659 ret = true;
660 break;
661 }
662 }
663 defn = foundDefn;
664 return ret;
665 }
666
667 // Pass through the settable parameters and set the default values
668 internal static void SetParameterDefaultValues(BSScene physicsScene)
669 {
670 foreach (ParameterDefn parm in ParameterDefinitions)
671 {
672 parm.setter(physicsScene, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
673 }
674 }
675
676 // Get user set values out of the ini file.
677 internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg)
678 {
679 foreach (ParameterDefn parm in ParameterDefinitions)
680 {
681 parm.userParam(physicsScene, cfg, parm.name, parm.defaultValue);
682 }
683 }
684
685 internal static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
686
687 // This creates an array in the correct format for returning the list of
688 // parameters. This is used by the 'list' option of the 'physics' command.
689 internal static void BuildParameterTable()
690 {
691 if (SettableParameters.Length < ParameterDefinitions.Length)
692 {
693 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
694 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
695 {
696 ParameterDefn pd = ParameterDefinitions[ii];
697 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
698 }
699
700 // make the list alphabetical for estetic reasons
701 entries.Sort((ppe1, ppe2) => { return ppe1.name.CompareTo(ppe2.name); });
702
703 SettableParameters = entries.ToArray();
704 }
705 }
706
707 private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v)
708 {
709 BSScene physScene = pPhysScene;
710 physScene.TaintedObject("BSParam.ResetBroadphasePoolTainted", delegate()
711 {
712 physScene.PE.ResetBroadphasePool(physScene.World);
713 });
714 }
715
716 private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
717 {
718 BSScene physScene = pPhysScene;
719 physScene.TaintedObject("BSParam.ResetConstraintSolver", delegate()
720 {
721 physScene.PE.ResetConstraintSolver(physScene.World);
722 });
723 }
724}
725}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index f6a890e..ec25aa9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -45,6 +45,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine. 45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine.
46 * The last two (and certainly the last one) should be referenced only in taint-time. 46 * The last two (and certainly the last one) should be referenced only in taint-time.
47 */ 47 */
48
49/*
50 * As of 20121221, the following are the call sequences (going down) for different script physical functions:
51 * llApplyImpulse llApplyRotImpulse llSetTorque llSetForce
52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce
53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse
54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v
55 * BS.ApplyCentralForce BS.ApplyTorque
56 */
57
58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc.
59public enum UpdatedProperties : uint
60{
61 Position = 1 << 0,
62 Orientation = 1 << 1,
63 Velocity = 1 << 2,
64 Acceleration = 1 << 3,
65 RotationalVelocity = 1 << 4,
66 EntPropUpdates = Position | Orientation | Velocity | Acceleration | RotationalVelocity,
67}
48public abstract class BSPhysObject : PhysicsActor 68public abstract class BSPhysObject : PhysicsActor
49{ 69{
50 protected BSPhysObject() 70 protected BSPhysObject()
@@ -55,15 +75,37 @@ public abstract class BSPhysObject : PhysicsActor
55 PhysicsScene = parentScene; 75 PhysicsScene = parentScene;
56 LocalID = localID; 76 LocalID = localID;
57 PhysObjectName = name; 77 PhysObjectName = name;
78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
58 TypeName = typeName; 79 TypeName = typeName;
59 80
81 // We don't have any physical representation yet.
82 PhysBody = new BulletBody(localID);
83 PhysShape = new BulletShape();
84
85 // A linkset of just me
60 Linkset = BSLinkset.Factory(PhysicsScene, this); 86 Linkset = BSLinkset.Factory(PhysicsScene, this);
87 PositionDisplacement = OMV.Vector3.Zero;
88
61 LastAssetBuildFailed = false; 89 LastAssetBuildFailed = false;
62 90
91 // Default material type
92 Material = MaterialAttributes.Material.Wood;
93
63 CollisionCollection = new CollisionEventUpdate(); 94 CollisionCollection = new CollisionEventUpdate();
95 CollisionsLastTick = CollisionCollection;
64 SubscribedEventsMs = 0; 96 SubscribedEventsMs = 0;
65 CollidingStep = 0; 97 CollidingStep = 0;
66 CollidingGroundStep = 0; 98 CollidingGroundStep = 0;
99 CollisionAccumulation = 0;
100 ColliderIsMoving = false;
101 CollisionScore = 0;
102 }
103
104 // Tell the object to clean up.
105 public virtual void Destroy()
106 {
107 UnRegisterAllPreStepActions();
108 UnRegisterAllPostStepActions();
67 } 109 }
68 110
69 public BSScene PhysicsScene { get; protected set; } 111 public BSScene PhysicsScene { get; protected set; }
@@ -72,11 +114,13 @@ public abstract class BSPhysObject : PhysicsActor
72 public string TypeName { get; protected set; } 114 public string TypeName { get; protected set; }
73 115
74 public BSLinkset Linkset { get; set; } 116 public BSLinkset Linkset { get; set; }
117 public BSLinksetInfo LinksetInfo { get; set; }
75 118
76 // Return the object mass without calculating it or having side effects 119 // Return the object mass without calculating it or having side effects
77 public abstract float RawMass { get; } 120 public abstract float RawMass { get; }
78 // Set the raw mass but also update physical mass properties (inertia, ...) 121 // Set the raw mass but also update physical mass properties (inertia, ...)
79 public abstract void UpdatePhysicalMassProperties(float mass); 122 // 'inWorld' true if the object has already been added to the dynamic world.
123 public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld);
80 124
81 // The last value calculated for the prim's inertia 125 // The last value calculated for the prim's inertia
82 public OMV.Vector3 Inertia { get; set; } 126 public OMV.Vector3 Inertia { get; set; }
@@ -105,9 +149,22 @@ public abstract class BSPhysObject : PhysicsActor
105 public EntityProperties CurrentEntityProperties { get; set; } 149 public EntityProperties CurrentEntityProperties { get; set; }
106 public EntityProperties LastEntityProperties { get; set; } 150 public EntityProperties LastEntityProperties { get; set; }
107 151
108 public abstract OMV.Vector3 Scale { get; set; } 152 public virtual OMV.Vector3 Scale { get; set; }
109 public abstract bool IsSolid { get; } 153 public abstract bool IsSolid { get; }
110 public abstract bool IsStatic { get; } 154 public abstract bool IsStatic { get; }
155 public abstract bool IsSelected { get; }
156
157 // It can be confusing for an actor to know if it should move or update an object
158 // depeneding on the setting of 'selected', 'physical, ...
159 // This flag is the true test -- if true, the object is being acted on in the physical world
160 public abstract bool IsPhysicallyActive { get; }
161
162 // Materialness
163 public MaterialAttributes.Material Material { get; private set; }
164 public override void SetMaterial(int material)
165 {
166 Material = (MaterialAttributes.Material)material;
167 }
111 168
112 // Stop all physical motion. 169 // Stop all physical motion.
113 public abstract void ZeroMotion(bool inTaintTime); 170 public abstract void ZeroMotion(bool inTaintTime);
@@ -119,15 +176,30 @@ public abstract class BSPhysObject : PhysicsActor
119 // Update the physical location and motion of the object. Called with data from Bullet. 176 // Update the physical location and motion of the object. Called with data from Bullet.
120 public abstract void UpdateProperties(EntityProperties entprop); 177 public abstract void UpdateProperties(EntityProperties entprop);
121 178
122 // Tell the object to clean up.
123 public abstract void Destroy();
124
125 public abstract OMV.Vector3 RawPosition { get; set; } 179 public abstract OMV.Vector3 RawPosition { get; set; }
126 public abstract OMV.Vector3 ForcePosition { get; set; } 180 public abstract OMV.Vector3 ForcePosition { get; set; }
127 181
182 // 'Position' and 'Orientation' is what the simulator thinks the positions of the prim is.
183 // Because Bullet needs the zero coordinate to be the center of mass of the linkset,
184 // sometimes it is necessary to displace the position the physics engine thinks
185 // the position is. PositionDisplacement must be added and removed from the
186 // position as the simulator position is stored and fetched from the physics
187 // engine. Similar to OrientationDisplacement.
188 public virtual OMV.Vector3 PositionDisplacement { get; set; }
189 public virtual OMV.Quaternion OrientationDisplacement { get; set; }
190
128 public abstract OMV.Quaternion RawOrientation { get; set; } 191 public abstract OMV.Quaternion RawOrientation { get; set; }
129 public abstract OMV.Quaternion ForceOrientation { get; set; } 192 public abstract OMV.Quaternion ForceOrientation { get; set; }
130 193
194 public virtual float TargetSpeed
195 {
196 get
197 {
198 OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
199 return characterOrientedVelocity.X;
200 }
201 }
202 public abstract OMV.Vector3 RawVelocity { get; set; }
131 public abstract OMV.Vector3 ForceVelocity { get; set; } 203 public abstract OMV.Vector3 ForceVelocity { get; set; }
132 204
133 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 205 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
@@ -136,6 +208,15 @@ public abstract class BSPhysObject : PhysicsActor
136 208
137 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 209 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
138 210
211 public virtual float ForwardSpeed
212 {
213 get
214 {
215 OMV.Vector3 characterOrientedVelocity = RawVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
216 return characterOrientedVelocity.X;
217 }
218 }
219
139 #region Collisions 220 #region Collisions
140 221
141 // Requested number of milliseconds between collision events. Zero means disabled. 222 // Requested number of milliseconds between collision events. Zero means disabled.
@@ -146,26 +227,71 @@ public abstract class BSPhysObject : PhysicsActor
146 protected long CollidingStep { get; set; } 227 protected long CollidingStep { get; set; }
147 // The simulation step that last had a collision with the ground 228 // The simulation step that last had a collision with the ground
148 protected long CollidingGroundStep { get; set; } 229 protected long CollidingGroundStep { get; set; }
230 // The simulation step that last collided with an object
231 protected long CollidingObjectStep { get; set; }
149 // The collision flags we think are set in Bullet 232 // The collision flags we think are set in Bullet
150 protected CollisionFlags CurrentCollisionFlags { get; set; } 233 protected CollisionFlags CurrentCollisionFlags { get; set; }
234 // On a collision, check the collider and remember if the last collider was moving
235 // Used to modify the standing of avatars (avatars on stationary things stand still)
236 protected bool ColliderIsMoving;
237
238 // Count of collisions for this object
239 protected long CollisionAccumulation { get; set; }
240
241 public override bool IsColliding {
242 get { return (CollidingStep == PhysicsScene.SimulationStep); }
243 set {
244 if (value)
245 CollidingStep = PhysicsScene.SimulationStep;
246 else
247 CollidingStep = 0;
248 }
249 }
250 public override bool CollidingGround {
251 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
252 set
253 {
254 if (value)
255 CollidingGroundStep = PhysicsScene.SimulationStep;
256 else
257 CollidingGroundStep = 0;
258 }
259 }
260 public override bool CollidingObj {
261 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); }
262 set {
263 if (value)
264 CollidingObjectStep = PhysicsScene.SimulationStep;
265 else
266 CollidingObjectStep = 0;
267 }
268 }
151 269
152 // The collisions that have been collected this tick 270 // The collisions that have been collected this tick
153 protected CollisionEventUpdate CollisionCollection; 271 protected CollisionEventUpdate CollisionCollection;
272 // Remember collisions from last tick for fancy collision based actions
273 // (like a BSCharacter walking up stairs).
274 protected CollisionEventUpdate CollisionsLastTick;
154 275
155 // The simulation step is telling this object about a collision. 276 // The simulation step is telling this object about a collision.
156 // Return 'true' if a collision was processed and should be sent up. 277 // Return 'true' if a collision was processed and should be sent up.
278 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision.
157 // Called at taint time from within the Step() function 279 // Called at taint time from within the Step() function
158 public virtual bool Collide(uint collidingWith, BSPhysObject collidee, 280 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
159 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 281 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
160 { 282 {
161 bool ret = false; 283 bool ret = false;
162 284
163 // The following lines make IsColliding() and IsCollidingGround() work 285 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
164 CollidingStep = PhysicsScene.SimulationStep; 286 CollidingStep = PhysicsScene.SimulationStep;
165 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 287 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
166 { 288 {
167 CollidingGroundStep = PhysicsScene.SimulationStep; 289 CollidingGroundStep = PhysicsScene.SimulationStep;
168 } 290 }
291 else
292 {
293 CollidingObjectStep = PhysicsScene.SimulationStep;
294 }
169 295
170 // prims in the same linkset cannot collide with each other 296 // prims in the same linkset cannot collide with each other
171 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) 297 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
@@ -173,7 +299,12 @@ public abstract class BSPhysObject : PhysicsActor
173 return ret; 299 return ret;
174 } 300 }
175 301
176 // if someone has subscribed for collision events.... 302 CollisionAccumulation++;
303
304 // For movement tests, remember if we are colliding with an object that is moving.
305 ColliderIsMoving = collidee != null ? collidee.RawVelocity != OMV.Vector3.Zero : false;
306
307 // If someone has subscribed for collision events log the collision so it will be reported up
177 if (SubscribedEvents()) { 308 if (SubscribedEvents()) {
178 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 309 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
179 DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", 310 DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
@@ -191,8 +322,9 @@ public abstract class BSPhysObject : PhysicsActor
191 public virtual bool SendCollisions() 322 public virtual bool SendCollisions()
192 { 323 {
193 bool ret = true; 324 bool ret = true;
325
194 // If the 'no collision' call, force it to happen right now so quick collision_end 326 // If the 'no collision' call, force it to happen right now so quick collision_end
195 bool force = CollisionCollection.Count == 0; 327 bool force = (CollisionCollection.Count == 0 && CollisionsLastTick.Count != 0);
196 328
197 // throttle the collisions to the number of milliseconds specified in the subscription 329 // throttle the collisions to the number of milliseconds specified in the subscription
198 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 330 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
@@ -207,11 +339,16 @@ public abstract class BSPhysObject : PhysicsActor
207 ret = false; 339 ret = false;
208 } 340 }
209 341
210 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); 342 DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
211 base.SendCollisionUpdate(CollisionCollection); 343 base.SendCollisionUpdate(CollisionCollection);
212 344
213 // The collisionCollection structure is passed around in the simulator. 345 // Remember the collisions from this tick for some collision specific processing.
346 CollisionsLastTick = CollisionCollection;
347
348 // The CollisionCollection instance is passed around in the simulator.
214 // Make sure we don't have a handle to that one and that a new one is used for next time. 349 // Make sure we don't have a handle to that one and that a new one is used for next time.
350 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
351 // a race condition is created for the other users of this instance.
215 CollisionCollection = new CollisionEventUpdate(); 352 CollisionCollection = new CollisionEventUpdate();
216 } 353 }
217 return ret; 354 return ret;
@@ -229,7 +366,8 @@ public abstract class BSPhysObject : PhysicsActor
229 366
230 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 367 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
231 { 368 {
232 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 369 if (PhysBody.HasPhysicalBody)
370 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
233 }); 371 });
234 } 372 }
235 else 373 else
@@ -243,21 +381,140 @@ public abstract class BSPhysObject : PhysicsActor
243 SubscribedEventsMs = 0; 381 SubscribedEventsMs = 0;
244 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 382 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
245 { 383 {
246 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 384 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
385 if (PhysBody.HasPhysicalBody)
386 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
247 }); 387 });
248 } 388 }
249 // Return 'true' if the simulator wants collision events 389 // Return 'true' if the simulator wants collision events
250 public override bool SubscribedEvents() { 390 public override bool SubscribedEvents() {
251 return (SubscribedEventsMs > 0); 391 return (SubscribedEventsMs > 0);
252 } 392 }
393 // Because 'CollisionScore' is called many times while sorting, it should not be recomputed
394 // each time called. So this is built to be light weight for each collision and to do
395 // all the processing when the user asks for the info.
396 public void ComputeCollisionScore()
397 {
398 // Scale the collision count by the time since the last collision.
399 // The "+1" prevents dividing by zero.
400 long timeAgo = PhysicsScene.SimulationStep - CollidingStep + 1;
401 CollisionScore = CollisionAccumulation / timeAgo;
402 }
403 public override float CollisionScore { get; set; }
253 404
254 #endregion // Collisions 405 #endregion // Collisions
255 406
407 #region Per Simulation Step actions
408 // There are some actions that must be performed for a physical object before each simulation step.
409 // These actions are optional so, rather than scanning all the physical objects and asking them
410 // if they have anything to do, a physical object registers for an event call before the step is performed.
411 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
412 private Dictionary<string, BSScene.PreStepAction> RegisteredPrestepActions = new Dictionary<string, BSScene.PreStepAction>();
413 private Dictionary<string, BSScene.PostStepAction> RegisteredPoststepActions = new Dictionary<string, BSScene.PostStepAction>();
414 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
415 {
416 string identifier = op + "-" + id.ToString();
417
418 lock (RegisteredPrestepActions)
419 {
420 // Clean out any existing action
421 UnRegisterPreStepAction(op, id);
422
423 RegisteredPrestepActions[identifier] = actn;
424
425 PhysicsScene.BeforeStep += actn;
426 }
427 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
428 }
429
430 // Unregister a pre step action. Safe to call if the action has not been registered.
431 // Returns 'true' if an action was actually removed
432 protected bool UnRegisterPreStepAction(string op, uint id)
433 {
434 string identifier = op + "-" + id.ToString();
435 bool removed = false;
436 lock (RegisteredPrestepActions)
437 {
438 if (RegisteredPrestepActions.ContainsKey(identifier))
439 {
440 PhysicsScene.BeforeStep -= RegisteredPrestepActions[identifier];
441 RegisteredPrestepActions.Remove(identifier);
442 removed = true;
443 }
444 }
445 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
446 return removed;
447 }
448
449 protected void UnRegisterAllPreStepActions()
450 {
451 lock (RegisteredPrestepActions)
452 {
453 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredPrestepActions)
454 {
455 PhysicsScene.BeforeStep -= kvp.Value;
456 }
457 RegisteredPrestepActions.Clear();
458 }
459 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
460 }
461
462 protected void RegisterPostStepAction(string op, uint id, BSScene.PostStepAction actn)
463 {
464 string identifier = op + "-" + id.ToString();
465
466 lock (RegisteredPoststepActions)
467 {
468 // Clean out any existing action
469 UnRegisterPostStepAction(op, id);
470
471 RegisteredPoststepActions[identifier] = actn;
472
473 PhysicsScene.AfterStep += actn;
474 }
475 DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
476 }
477
478 // Unregister a pre step action. Safe to call if the action has not been registered.
479 // Returns 'true' if an action was actually removed.
480 protected bool UnRegisterPostStepAction(string op, uint id)
481 {
482 string identifier = op + "-" + id.ToString();
483 bool removed = false;
484 lock (RegisteredPoststepActions)
485 {
486 if (RegisteredPoststepActions.ContainsKey(identifier))
487 {
488 PhysicsScene.AfterStep -= RegisteredPoststepActions[identifier];
489 RegisteredPoststepActions.Remove(identifier);
490 removed = true;
491 }
492 }
493 DetailLog("{0},BSPhysObject.UnRegisterPostStepAction,id={1},removed={2}", LocalID, identifier, removed);
494 return removed;
495 }
496
497 protected void UnRegisterAllPostStepActions()
498 {
499 lock (RegisteredPoststepActions)
500 {
501 foreach (KeyValuePair<string, BSScene.PostStepAction> kvp in RegisteredPoststepActions)
502 {
503 PhysicsScene.AfterStep -= kvp.Value;
504 }
505 RegisteredPoststepActions.Clear();
506 }
507 DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
508 }
509
510 #endregion // Per Simulation Step actions
511
256 // High performance detailed logging routine used by the physical objects. 512 // High performance detailed logging routine used by the physical objects.
257 protected void DetailLog(string msg, params Object[] args) 513 protected void DetailLog(string msg, params Object[] args)
258 { 514 {
259 if (PhysicsScene.PhysicsLogging.Enabled) 515 if (PhysicsScene.PhysicsLogging.Enabled)
260 PhysicsScene.DetailLog(msg, args); 516 PhysicsScene.DetailLog(msg, args);
261 } 517 }
518
262} 519}
263} 520}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
index 20f5180..9442854 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
@@ -59,13 +59,7 @@ public class BSPlugin : IPhysicsPlugin
59 { 59 {
60 if (_mScene == null) 60 if (_mScene == null)
61 { 61 {
62 if (Util.IsWindows()) 62 _mScene = new BSScene(GetName(), sceneIdentifier);
63 Util.LoadArchSpecificWindowsDll("BulletSim.dll");
64 // If not Windows, loading is performed by the
65 // Mono loader as specified in
66 // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config".
67
68 _mScene = new BSScene(sceneIdentifier);
69 } 63 }
70 return (_mScene); 64 return (_mScene);
71 } 65 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 2b3fa25..54bf063 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -45,19 +45,20 @@ public sealed class BSPrim : BSPhysObject
45 private static readonly string LogHeader = "[BULLETS PRIM]"; 45 private static readonly string LogHeader = "[BULLETS PRIM]";
46 46
47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. 47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
48 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
49 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user 48 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
50 49
51 private bool _grabbed; 50 private bool _grabbed;
52 private bool _isSelected; 51 private bool _isSelected;
53 private bool _isVolumeDetect; 52 private bool _isVolumeDetect;
53
54 // _position is what the simulator thinks the positions of the prim is.
54 private OMV.Vector3 _position; 55 private OMV.Vector3 _position;
56
55 private float _mass; // the mass of this object 57 private float _mass; // the mass of this object
56 private float _density; 58 private float _density;
57 private OMV.Vector3 _force; 59 private OMV.Vector3 _force;
58 private OMV.Vector3 _velocity; 60 private OMV.Vector3 _velocity;
59 private OMV.Vector3 _torque; 61 private OMV.Vector3 _torque;
60 private float _collisionScore;
61 private OMV.Vector3 _acceleration; 62 private OMV.Vector3 _acceleration;
62 private OMV.Quaternion _orientation; 63 private OMV.Quaternion _orientation;
63 private int _physicsActorType; 64 private int _physicsActorType;
@@ -67,23 +68,21 @@ public sealed class BSPrim : BSPhysObject
67 private float _restitution; 68 private float _restitution;
68 private bool _setAlwaysRun; 69 private bool _setAlwaysRun;
69 private bool _throttleUpdates; 70 private bool _throttleUpdates;
70 private bool _isColliding;
71 private bool _collidingGround;
72 private bool _collidingObj;
73 private bool _floatOnWater; 71 private bool _floatOnWater;
74 private OMV.Vector3 _rotationalVelocity; 72 private OMV.Vector3 _rotationalVelocity;
75 private bool _kinematic; 73 private bool _kinematic;
76 private float _buoyancy; 74 private float _buoyancy;
77 75
78 private BSDynamics _vehicle; 76 public BSDynamics VehicleController { get; private set; }
79 77
78 private BSVMotor _targetMotor;
80 private OMV.Vector3 _PIDTarget; 79 private OMV.Vector3 _PIDTarget;
81 private bool _usePID;
82 private float _PIDTau; 80 private float _PIDTau;
83 private bool _useHoverPID; 81
82 private BSFMotor _hoverMotor;
84 private float _PIDHoverHeight; 83 private float _PIDHoverHeight;
85 private PIDHoverType _PIDHoverType; 84 private PIDHoverType _PIDHoverType;
86 private float _PIDHoverTao; 85 private float _PIDHoverTau;
87 86
88 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 87 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
89 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 88 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
@@ -93,23 +92,27 @@ public sealed class BSPrim : BSPhysObject
93 _physicsActorType = (int)ActorTypes.Prim; 92 _physicsActorType = (int)ActorTypes.Prim;
94 _position = pos; 93 _position = pos;
95 _size = size; 94 _size = size;
96 Scale = size; // the scale will be set by CreateGeom depending on object type 95 Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
97 _orientation = rotation; 96 _orientation = rotation;
98 _buoyancy = 1f; 97 _buoyancy = 0f;
99 _velocity = OMV.Vector3.Zero; 98 _velocity = OMV.Vector3.Zero;
100 _rotationalVelocity = OMV.Vector3.Zero; 99 _rotationalVelocity = OMV.Vector3.Zero;
101 BaseShape = pbs; 100 BaseShape = pbs;
102 _isPhysical = pisPhysical; 101 _isPhysical = pisPhysical;
103 _isVolumeDetect = false; 102 _isVolumeDetect = false;
104 _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material 103
105 _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material 104 // Someday set default attributes based on the material but, for now, we don't know the prim material yet.
105 // MaterialAttributes primMat = BSMaterials.GetAttributes(Material, pisPhysical);
106 _density = PhysicsScene.Params.defaultDensity;
107 _friction = PhysicsScene.Params.defaultFriction;
106 _restitution = PhysicsScene.Params.defaultRestitution; 108 _restitution = PhysicsScene.Params.defaultRestitution;
107 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness 109
110 VehicleController = new BSDynamics(PhysicsScene, this); // add vehicleness
111
108 _mass = CalculateMass(); 112 _mass = CalculateMass();
109 113
110 // No body or shape yet 114 // Cause linkset variables to be initialized (like mass)
111 PhysBody = new BulletBody(LocalID, IntPtr.Zero); 115 Linkset.Refresh(this);
112 PhysShape = new BulletShape(IntPtr.Zero);
113 116
114 DetailLog("{0},BSPrim.constructor,call", LocalID); 117 DetailLog("{0},BSPrim.constructor,call", LocalID);
115 // do the actual object creation at taint time 118 // do the actual object creation at taint time
@@ -117,7 +120,7 @@ public sealed class BSPrim : BSPhysObject
117 { 120 {
118 CreateGeomAndObject(true); 121 CreateGeomAndObject(true);
119 122
120 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr); 123 CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody);
121 }); 124 });
122 } 125 }
123 126
@@ -125,10 +128,11 @@ public sealed class BSPrim : BSPhysObject
125 public override void Destroy() 128 public override void Destroy()
126 { 129 {
127 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 130 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
131 base.Destroy();
128 132
129 // Undo any links between me and any other object 133 // Undo any links between me and any other object
130 BSPhysObject parentBefore = Linkset.LinksetRoot; 134 BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG DEBUG
131 int childrenBefore = Linkset.NumberOfChildren; 135 int childrenBefore = Linkset.NumberOfChildren; // DEBUG DEBUG
132 136
133 Linkset = Linkset.RemoveMeFromLinkset(this); 137 Linkset = Linkset.RemoveMeFromLinkset(this);
134 138
@@ -142,8 +146,10 @@ public sealed class BSPrim : BSPhysObject
142 { 146 {
143 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 147 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
144 // If there are physical body and shape, release my use of same. 148 // If there are physical body and shape, release my use of same.
145 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); 149 PhysicsScene.Shapes.DereferenceBody(PhysBody, null);
146 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); 150 PhysBody.Clear();
151 PhysicsScene.Shapes.DereferenceShape(PhysShape, null);
152 PhysShape.Clear();
147 }); 153 });
148 } 154 }
149 155
@@ -157,16 +163,15 @@ public sealed class BSPrim : BSPhysObject
157 // We presume the scale and size are the same. If scale must be changed for 163 // We presume the scale and size are the same. If scale must be changed for
158 // the physical shape, that is done when the geometry is built. 164 // the physical shape, that is done when the geometry is built.
159 _size = value; 165 _size = value;
166 Scale = _size;
160 ForceBodyShapeRebuild(false); 167 ForceBodyShapeRebuild(false);
161 } 168 }
162 } 169 }
163 // Scale is what we set in the physics engine. It is different than 'size' in that
164 // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>.
165 public override OMV.Vector3 Scale { get; set; }
166 170
167 public override PrimitiveBaseShape Shape { 171 public override PrimitiveBaseShape Shape {
168 set { 172 set {
169 BaseShape = value; 173 BaseShape = value;
174 LastAssetBuildFailed = false;
170 ForceBodyShapeRebuild(false); 175 ForceBodyShapeRebuild(false);
171 } 176 }
172 } 177 }
@@ -176,12 +181,19 @@ public sealed class BSPrim : BSPhysObject
176 181
177 public override bool ForceBodyShapeRebuild(bool inTaintTime) 182 public override bool ForceBodyShapeRebuild(bool inTaintTime)
178 { 183 {
179 LastAssetBuildFailed = false; 184 if (inTaintTime)
180 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
181 { 185 {
182 _mass = CalculateMass(); // changing the shape changes the mass 186 _mass = CalculateMass(); // changing the shape changes the mass
183 CreateGeomAndObject(true); 187 CreateGeomAndObject(true);
184 }); 188 }
189 else
190 {
191 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
192 {
193 _mass = CalculateMass(); // changing the shape changes the mass
194 CreateGeomAndObject(true);
195 });
196 }
185 return true; 197 return true;
186 } 198 }
187 public override bool Grabbed { 199 public override bool Grabbed {
@@ -189,15 +201,23 @@ public sealed class BSPrim : BSPhysObject
189 } 201 }
190 } 202 }
191 public override bool Selected { 203 public override bool Selected {
192 set { 204 set
193 _isSelected = value; 205 {
194 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() 206 if (value != _isSelected)
195 { 207 {
196 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); 208 _isSelected = value;
197 SetObjectDynamic(false); 209 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
198 }); 210 {
211 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
212 SetObjectDynamic(false);
213 });
214 }
199 } 215 }
200 } 216 }
217 public override bool IsSelected
218 {
219 get { return _isSelected; }
220 }
201 public override void CrossingFailure() { return; } 221 public override void CrossingFailure() { return; }
202 222
203 // link me to the specified parent 223 // link me to the specified parent
@@ -244,7 +264,8 @@ public sealed class BSPrim : BSPhysObject
244 // Zero some other properties in the physics engine 264 // Zero some other properties in the physics engine
245 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 265 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
246 { 266 {
247 BulletSimAPI.ClearAllForces2(PhysBody.ptr); 267 if (PhysBody.HasPhysicalBody)
268 PhysicsScene.PE.ClearAllForces(PhysBody);
248 }); 269 });
249 } 270 }
250 public override void ZeroAngularMotion(bool inTaintTime) 271 public override void ZeroAngularMotion(bool inTaintTime)
@@ -253,8 +274,12 @@ public sealed class BSPrim : BSPhysObject
253 // Zero some other properties in the physics engine 274 // Zero some other properties in the physics engine
254 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 275 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
255 { 276 {
256 BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); 277 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
257 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); 278 if (PhysBody.HasPhysicalBody)
279 {
280 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
281 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
282 }
258 }); 283 });
259 } 284 }
260 285
@@ -271,41 +296,52 @@ public sealed class BSPrim : BSPhysObject
271 } 296 }
272 public override OMV.Vector3 Position { 297 public override OMV.Vector3 Position {
273 get { 298 get {
299 /* NOTE: this refetch is not necessary. The simulator knows about linkset children
300 * and does not fetch this position info for children. Thus this is commented out.
274 // child prims move around based on their parent. Need to get the latest location 301 // child prims move around based on their parent. Need to get the latest location
275 if (!Linkset.IsRoot(this)) 302 if (!Linkset.IsRoot(this))
276 _position = Linkset.Position(this); 303 _position = Linkset.PositionGet(this);
304 */
277 305
278 // don't do the GetObjectPosition for root elements because this function is called a zillion times. 306 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
279 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 307 // _position = PhysicsScene.PE.GetObjectPosition2(PhysicsScene.World, BSBody) - PositionDisplacement;
280 return _position; 308 return _position;
281 } 309 }
282 set { 310 set {
283 // If the position must be forced into the physics engine, use ForcePosition. 311 // If the position must be forced into the physics engine, use ForcePosition.
312 // All positions are given in world positions.
284 if (_position == value) 313 if (_position == value)
285 { 314 {
315 DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation);
286 return; 316 return;
287 } 317 }
288 _position = value; 318 _position = value;
289 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
290 PositionSanityCheck(false); 319 PositionSanityCheck(false);
320
291 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 321 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
292 { 322 {
293 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 323 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
294 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 324 ForcePosition = _position;
295 ActivateIfPhysical(false); 325
326 // A linkset might need to know if a component information changed.
327 Linkset.UpdateProperties(UpdatedProperties.Position, this);
328
296 }); 329 });
297 } 330 }
298 } 331 }
332
299 public override OMV.Vector3 ForcePosition { 333 public override OMV.Vector3 ForcePosition {
300 get { 334 get {
301 _position = BulletSimAPI.GetPosition2(PhysBody.ptr); 335 _position = PhysicsScene.PE.GetPosition(PhysBody) - PositionDisplacement;
302 return _position; 336 return _position;
303 } 337 }
304 set { 338 set {
305 _position = value; 339 _position = value;
306 // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better. 340 if (PhysBody.HasPhysicalBody)
307 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 341 {
308 ActivateIfPhysical(false); 342 PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
343 ActivateIfPhysical(false);
344 }
309 } 345 }
310 } 346 }
311 347
@@ -316,51 +352,64 @@ public sealed class BSPrim : BSPhysObject
316 { 352 {
317 bool ret = false; 353 bool ret = false;
318 354
319 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); 355 // We don't care where non-physical items are placed
356 if (!IsPhysicallyActive)
357 return ret;
358
359 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
360 {
361 // The physical object is out of the known/simulated area.
362 // Upper levels of code will handle the transition to other areas so, for
363 // the time, we just ignore the position.
364 return ret;
365 }
366
367 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
320 OMV.Vector3 upForce = OMV.Vector3.Zero; 368 OMV.Vector3 upForce = OMV.Vector3.Zero;
321 if (Position.Z < terrainHeight) 369 if (RawPosition.Z < terrainHeight)
322 { 370 {
323 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 371 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight);
324 float targetHeight = terrainHeight + (Size.Z / 2f); 372 float targetHeight = terrainHeight + (Size.Z / 2f);
325 // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. 373 // If the object is below ground it just has to be moved up because pushing will
326 upForce.Z = (terrainHeight - Position.Z) * 1f; 374 // not get it through the terrain
375 _position.Z = targetHeight;
376 if (inTaintTime)
377 {
378 ForcePosition = _position;
379 }
380 // If we are throwing the object around, zero its other forces
381 ZeroMotion(inTaintTime);
327 ret = true; 382 ret = true;
328 } 383 }
329 384
330 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 385 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
331 { 386 {
332 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); 387 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
333 // TODO: a floating motor so object will bob in the water 388 // TODO: a floating motor so object will bob in the water
334 if (Math.Abs(Position.Z - waterHeight) > 0.1f) 389 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f)
335 { 390 {
336 // Upforce proportional to the distance away from the water. Correct the error in 1 sec. 391 // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
337 upForce.Z = (waterHeight - Position.Z) * 1f; 392 upForce.Z = (waterHeight - RawPosition.Z) * 1f;
393
394 // Apply upforce and overcome gravity.
395 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity;
396 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
397 AddForce(correctionForce, false, inTaintTime);
338 ret = true; 398 ret = true;
339 } 399 }
340 } 400 }
341 401
342 // TODO: check for out of bounds
343
344 // The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
345 if (ret)
346 {
347 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck:belowTerrain", delegate()
348 {
349 // Apply upforce and overcome gravity.
350 ForceVelocity = ForceVelocity + upForce - PhysicsScene.DefaultGravity;
351 });
352 }
353 return ret; 402 return ret;
354 } 403 }
355 404
356 // Return the effective mass of the object. 405 // Return the effective mass of the object.
357 // If there are multiple items in the linkset, add them together for the root 406 // The definition of this call is to return the mass of the prim.
407 // If the simulator cares about the mass of the linkset, it will sum it itself.
358 public override float Mass 408 public override float Mass
359 { 409 {
360 get 410 get
361 { 411 {
362 return Linkset.LinksetMass; 412 return _mass;
363 // return _mass;
364 } 413 }
365 } 414 }
366 415
@@ -370,25 +419,64 @@ public sealed class BSPrim : BSPhysObject
370 } 419 }
371 // Set the physical mass to the passed mass. 420 // Set the physical mass to the passed mass.
372 // Note that this does not change _mass! 421 // Note that this does not change _mass!
373 public override void UpdatePhysicalMassProperties(float physMass) 422 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
374 { 423 {
375 if (IsStatic) 424 if (PhysBody.HasPhysicalBody)
376 { 425 {
377 Inertia = OMV.Vector3.Zero; 426 if (IsStatic)
378 BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia); 427 {
379 BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); 428 PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity);
380 } 429 Inertia = OMV.Vector3.Zero;
381 else 430 PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia);
382 { 431 PhysicsScene.PE.UpdateInertiaTensor(PhysBody);
383 Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); 432 }
384 BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia); 433 else
385 BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); 434 {
386 // center of mass is at the zero of the object 435 OMV.Vector3 grav = ComputeGravity(Buoyancy);
387 // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); 436
388 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, Inertia); 437 if (inWorld)
438 {
439 // Changing interesting properties doesn't change proxy and collision cache
440 // information. The Bullet solution is to re-add the object to the world
441 // after parameters are changed.
442 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody);
443 }
444
445 // The computation of mass props requires gravity to be set on the object.
446 PhysicsScene.PE.SetGravity(PhysBody, grav);
447
448 Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass);
449 PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia);
450 PhysicsScene.PE.UpdateInertiaTensor(PhysBody);
451
452 // center of mass is at the zero of the object
453 // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(PhysBody, ForcePosition, ForceOrientation);
454 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", LocalID, physMass, Inertia, grav, inWorld);
455
456 if (inWorld)
457 {
458 AddObjectToPhysicalWorld();
459 }
460
461 // Must set gravity after it has been added to the world because, for unknown reasons,
462 // adding the object resets the object's gravity to world gravity
463 PhysicsScene.PE.SetGravity(PhysBody, grav);
464
465 }
389 } 466 }
390 } 467 }
391 468
469 // Return what gravity should be set to this very moment
470 public OMV.Vector3 ComputeGravity(float buoyancy)
471 {
472 OMV.Vector3 ret = PhysicsScene.DefaultGravity;
473
474 if (!IsStatic)
475 ret *= (1f - buoyancy);
476
477 return ret;
478 }
479
392 // Is this used? 480 // Is this used?
393 public override OMV.Vector3 CenterOfMass 481 public override OMV.Vector3 CenterOfMass
394 { 482 {
@@ -405,30 +493,60 @@ public sealed class BSPrim : BSPhysObject
405 get { return _force; } 493 get { return _force; }
406 set { 494 set {
407 _force = value; 495 _force = value;
408 PhysicsScene.TaintedObject("BSPrim.setForce", delegate() 496 if (_force != OMV.Vector3.Zero)
409 { 497 {
410 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 498 // If the force is non-zero, it must be reapplied each tick because
411 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); 499 // Bullet clears the forces applied last frame.
412 }); 500 RegisterPreStepAction("BSPrim.setForce", LocalID,
501 delegate(float timeStep)
502 {
503 if (!IsPhysicallyActive)
504 {
505 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
506 return;
507 }
508
509 DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force);
510 if (PhysBody.HasPhysicalBody)
511 {
512 PhysicsScene.PE.ApplyCentralForce(PhysBody, _force);
513 ActivateIfPhysical(false);
514 }
515 }
516 );
517 }
518 else
519 {
520 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
521 }
413 } 522 }
414 } 523 }
415 524
416 public override int VehicleType { 525 public override int VehicleType {
417 get { 526 get {
418 return (int)_vehicle.Type; // if we are a vehicle, return that type 527 return (int)VehicleController.Type; // if we are a vehicle, return that type
419 } 528 }
420 set { 529 set {
421 Vehicle type = (Vehicle)value; 530 Vehicle type = (Vehicle)value;
422 531
423 // Tell the scene about the vehicle so it will get processing each frame.
424 PhysicsScene.VehicleInSceneTypeChanged(this, type);
425
426 PhysicsScene.TaintedObject("setVehicleType", delegate() 532 PhysicsScene.TaintedObject("setVehicleType", delegate()
427 { 533 {
428 // Done at taint time so we're sure the physics engine is not using the variables 534 // Done at taint time so we're sure the physics engine is not using the variables
429 // Vehicle code changes the parameters for this vehicle type. 535 // Vehicle code changes the parameters for this vehicle type.
430 _vehicle.ProcessTypeChange(type); 536 VehicleController.ProcessTypeChange(type);
431 ActivateIfPhysical(false); 537 ActivateIfPhysical(false);
538
539 // If an active vehicle, register the vehicle code to be called before each step
540 if (VehicleController.Type == Vehicle.TYPE_NONE)
541 {
542 UnRegisterPreStepAction("BSPrim.Vehicle", LocalID);
543 PhysicsScene.AfterStep -= VehicleController.PostStep;
544 }
545 else
546 {
547 RegisterPreStepAction("BSPrim.Vehicle", LocalID, VehicleController.Step);
548 PhysicsScene.AfterStep += VehicleController.PostStep;
549 }
432 }); 550 });
433 } 551 }
434 } 552 }
@@ -436,7 +554,7 @@ public sealed class BSPrim : BSPhysObject
436 { 554 {
437 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 555 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
438 { 556 {
439 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 557 VehicleController.ProcessFloatVehicleParam((Vehicle)param, value);
440 ActivateIfPhysical(false); 558 ActivateIfPhysical(false);
441 }); 559 });
442 } 560 }
@@ -444,7 +562,7 @@ public sealed class BSPrim : BSPhysObject
444 { 562 {
445 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 563 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
446 { 564 {
447 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 565 VehicleController.ProcessVectorVehicleParam((Vehicle)param, value);
448 ActivateIfPhysical(false); 566 ActivateIfPhysical(false);
449 }); 567 });
450 } 568 }
@@ -452,7 +570,7 @@ public sealed class BSPrim : BSPhysObject
452 { 570 {
453 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 571 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
454 { 572 {
455 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 573 VehicleController.ProcessRotationVehicleParam((Vehicle)param, rotation);
456 ActivateIfPhysical(false); 574 ActivateIfPhysical(false);
457 }); 575 });
458 } 576 }
@@ -460,27 +578,10 @@ public sealed class BSPrim : BSPhysObject
460 { 578 {
461 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() 579 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate()
462 { 580 {
463 _vehicle.ProcessVehicleFlags(param, remove); 581 VehicleController.ProcessVehicleFlags(param, remove);
464 }); 582 });
465 } 583 }
466 584
467 // Called each simulation step to advance vehicle characteristics.
468 // Called from Scene when doing simulation step so we're in taint processing time.
469 public override void StepVehicle(float timeStep)
470 {
471 if (IsPhysical && _vehicle.IsActive)
472 {
473 _vehicle.Step(timeStep);
474 /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step
475 PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate()
476 {
477 // This resets the interpolation values and recomputes the tensor variables
478 BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation);
479 });
480 */
481 }
482 }
483
484 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 585 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
485 public override void SetVolumeDetect(int param) { 586 public override void SetVolumeDetect(int param) {
486 bool newValue = (param != 0); 587 bool newValue = (param != 0);
@@ -495,6 +596,11 @@ public sealed class BSPrim : BSPhysObject
495 } 596 }
496 return; 597 return;
497 } 598 }
599 public override OMV.Vector3 RawVelocity
600 {
601 get { return _velocity; }
602 set { _velocity = value; }
603 }
498 public override OMV.Vector3 Velocity { 604 public override OMV.Vector3 Velocity {
499 get { return _velocity; } 605 get { return _velocity; }
500 set { 606 set {
@@ -502,30 +608,53 @@ public sealed class BSPrim : BSPhysObject
502 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 608 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
503 { 609 {
504 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 610 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
505 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); 611 ForceVelocity = _velocity;
506 }); 612 });
507 } 613 }
508 } 614 }
509 public override OMV.Vector3 ForceVelocity { 615 public override OMV.Vector3 ForceVelocity {
510 get { return _velocity; } 616 get { return _velocity; }
511 set { 617 set {
618 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity");
619
512 _velocity = value; 620 _velocity = value;
513 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); 621 if (PhysBody.HasPhysicalBody)
622 {
623 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity);
624 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
625 ActivateIfPhysical(false);
626 }
514 } 627 }
515 } 628 }
516 public override OMV.Vector3 Torque { 629 public override OMV.Vector3 Torque {
517 get { return _torque; } 630 get { return _torque; }
518 set { 631 set {
519 _torque = value; 632 _torque = value;
520 AddAngularForce(_torque, false, false); 633 if (_torque != OMV.Vector3.Zero)
634 {
635 // If the torque is non-zero, it must be reapplied each tick because
636 // Bullet clears the forces applied last frame.
637 RegisterPreStepAction("BSPrim.setTorque", LocalID,
638 delegate(float timeStep)
639 {
640 if (!IsPhysicallyActive)
641 {
642 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
643 return;
644 }
645
646 if (PhysBody.HasPhysicalBody)
647 AddAngularForce(_torque, false, true);
648 }
649 );
650 }
651 else
652 {
653 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
654 }
521 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 655 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
522 } 656 }
523 } 657 }
524 public override float CollisionScore {
525 get { return _collisionScore; }
526 set { _collisionScore = value;
527 }
528 }
529 public override OMV.Vector3 Acceleration { 658 public override OMV.Vector3 Acceleration {
530 get { return _acceleration; } 659 get { return _acceleration; }
531 set { _acceleration = value; } 660 set { _acceleration = value; }
@@ -537,23 +666,28 @@ public sealed class BSPrim : BSPhysObject
537 } 666 }
538 public override OMV.Quaternion Orientation { 667 public override OMV.Quaternion Orientation {
539 get { 668 get {
669 /* NOTE: this refetch is not necessary. The simulator knows about linkset children
670 * and does not fetch this position info for children. Thus this is commented out.
540 // Children move around because tied to parent. Get a fresh value. 671 // Children move around because tied to parent. Get a fresh value.
541 if (!Linkset.IsRoot(this)) 672 if (!Linkset.IsRoot(this))
542 { 673 {
543 _orientation = Linkset.Orientation(this); 674 _orientation = Linkset.OrientationGet(this);
544 } 675 }
676 */
545 return _orientation; 677 return _orientation;
546 } 678 }
547 set { 679 set {
548 if (_orientation == value) 680 if (_orientation == value)
549 return; 681 return;
550 _orientation = value; 682 _orientation = value;
551 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 683
552 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 684 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
553 { 685 {
554 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 686 ForceOrientation = _orientation;
555 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 687
556 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 688 // A linkset might need to know if a component information changed.
689 Linkset.UpdateProperties(UpdatedProperties.Orientation, this);
690
557 }); 691 });
558 } 692 }
559 } 693 }
@@ -562,13 +696,14 @@ public sealed class BSPrim : BSPhysObject
562 { 696 {
563 get 697 get
564 { 698 {
565 _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); 699 _orientation = PhysicsScene.PE.GetOrientation(PhysBody);
566 return _orientation; 700 return _orientation;
567 } 701 }
568 set 702 set
569 { 703 {
570 _orientation = value; 704 _orientation = value;
571 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 705 if (PhysBody.HasPhysicalBody)
706 PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
572 } 707 }
573 } 708 }
574 public override int PhysicsActorType { 709 public override int PhysicsActorType {
@@ -583,7 +718,7 @@ public sealed class BSPrim : BSPhysObject
583 _isPhysical = value; 718 _isPhysical = value;
584 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() 719 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate()
585 { 720 {
586 // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 721 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
587 SetObjectDynamic(true); 722 SetObjectDynamic(true);
588 // whether phys-to-static or static-to-phys, the object is not moving. 723 // whether phys-to-static or static-to-phys, the object is not moving.
589 ZeroMotion(true); 724 ZeroMotion(true);
@@ -604,6 +739,12 @@ public sealed class BSPrim : BSPhysObject
604 get { return !IsPhantom && !_isVolumeDetect; } 739 get { return !IsPhantom && !_isVolumeDetect; }
605 } 740 }
606 741
742 // The object is moving and is actively being dynamic in the physical world
743 public override bool IsPhysicallyActive
744 {
745 get { return !_isSelected && IsPhysical; }
746 }
747
607 // Make gravity work if the object is physical and not selected 748 // Make gravity work if the object is physical and not selected
608 // Called at taint-time!! 749 // Called at taint-time!!
609 private void SetObjectDynamic(bool forceRebuild) 750 private void SetObjectDynamic(bool forceRebuild)
@@ -618,19 +759,19 @@ public sealed class BSPrim : BSPhysObject
618 // isSolid: other objects bounce off of this object 759 // isSolid: other objects bounce off of this object
619 // isVolumeDetect: other objects pass through but can generate collisions 760 // isVolumeDetect: other objects pass through but can generate collisions
620 // collisionEvents: whether this object returns collision events 761 // collisionEvents: whether this object returns collision events
621 private void UpdatePhysicalParameters() 762 public void UpdatePhysicalParameters()
622 { 763 {
623 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); 764 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
624 765
625 // Mangling all the physical properties requires the object not be in the physical world. 766 // Mangling all the physical properties requires the object not be in the physical world.
626 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). 767 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
627 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); 768 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody);
628 769
629 // Set up the object physicalness (does gravity and collisions move this object) 770 // Set up the object physicalness (does gravity and collisions move this object)
630 MakeDynamic(IsStatic); 771 MakeDynamic(IsStatic);
631 772
632 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) 773 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
633 _vehicle.Refresh(); 774 VehicleController.Refresh();
634 775
635 // Arrange for collision events if the simulator wants them 776 // Arrange for collision events if the simulator wants them
636 EnableCollisions(SubscribedEvents()); 777 EnableCollisions(SubscribedEvents());
@@ -638,16 +779,10 @@ public sealed class BSPrim : BSPhysObject
638 // Make solid or not (do things bounce off or pass through this object). 779 // Make solid or not (do things bounce off or pass through this object).
639 MakeSolid(IsSolid); 780 MakeSolid(IsSolid);
640 781
641 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); 782 AddObjectToPhysicalWorld();
642 783
643 // Rebuild its shape 784 // Rebuild its shape
644 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); 785 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody);
645
646 // Collision filter can be set only when the object is in the world
647 if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0)
648 {
649 BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask);
650 }
651 786
652 // Recompute any linkset parameters. 787 // Recompute any linkset parameters.
653 // When going from non-physical to physical, this re-enables the constraints that 788 // When going from non-physical to physical, this re-enables the constraints that
@@ -655,8 +790,8 @@ public sealed class BSPrim : BSPhysObject
655 // For compound based linksets, this enables and disables interactions of the children. 790 // For compound based linksets, this enables and disables interactions of the children.
656 Linkset.Refresh(this); 791 Linkset.Refresh(this);
657 792
658 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", 793 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
659 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape); 794 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
660 } 795 }
661 796
662 // "Making dynamic" means changing to and from static. 797 // "Making dynamic" means changing to and from static.
@@ -669,74 +804,80 @@ public sealed class BSPrim : BSPhysObject
669 if (makeStatic) 804 if (makeStatic)
670 { 805 {
671 // Become a Bullet 'static' object type 806 // Become a Bullet 'static' object type
672 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 807 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
673 // Stop all movement 808 // Stop all movement
674 ZeroMotion(true); 809 ZeroMotion(true);
675 // Center of mass is at the center of the object 810
676 // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); 811 // Set various physical properties so other object interact properly
812 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
813 PhysicsScene.PE.SetFriction(PhysBody, matAttrib.friction);
814 PhysicsScene.PE.SetRestitution(PhysBody, matAttrib.restitution);
815
677 // Mass is zero which disables a bunch of physics stuff in Bullet 816 // Mass is zero which disables a bunch of physics stuff in Bullet
678 UpdatePhysicalMassProperties(0f); 817 UpdatePhysicalMassProperties(0f, false);
679 // Set collision detection parameters 818 // Set collision detection parameters
680 if (PhysicsScene.Params.ccdMotionThreshold > 0f) 819 if (BSParam.CcdMotionThreshold > 0f)
681 { 820 {
682 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); 821 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
683 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); 822 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
684 } 823 }
685 // There can be special things needed for implementing linksets 824
686 Linkset.MakeStatic(this);
687 // The activation state is 'disabled' so Bullet will not try to act on it. 825 // The activation state is 'disabled' so Bullet will not try to act on it.
688 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); 826 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION);
689 // Start it out sleeping and physical actions could wake it up. 827 // Start it out sleeping and physical actions could wake it up.
690 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); 828 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING);
829
830 // This collides like a static object
831 PhysBody.collisionType = CollisionType.Static;
691 832
692 PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; 833 // There can be special things needed for implementing linksets
693 PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask; 834 Linkset.MakeStatic(this);
694 } 835 }
695 else 836 else
696 { 837 {
697 // Not a Bullet static object 838 // Not a Bullet static object
698 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 839 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
699 840
700 // Set various physical properties so internal dynamic properties will get computed correctly as they are set 841 // Set various physical properties so other object interact properly
701 BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction); 842 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, true);
702 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution); 843 PhysicsScene.PE.SetFriction(PhysBody, matAttrib.friction);
844 PhysicsScene.PE.SetRestitution(PhysBody, matAttrib.restitution);
703 845
704 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 846 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
705 // Since this can be called multiple times, only zero forces when becoming physical 847 // Since this can be called multiple times, only zero forces when becoming physical
706 // BulletSimAPI.ClearAllForces2(BSBody.ptr); 848 // PhysicsScene.PE.ClearAllForces(BSBody);
707 849
708 // For good measure, make sure the transform is set through to the motion state 850 // For good measure, make sure the transform is set through to the motion state
709 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 851 PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
710 852
711 // Center of mass is at the center of the object 853 // Center of mass is at the center of the object
712 // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); 854 // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation);
713 855
714 // A dynamic object has mass 856 // A dynamic object has mass
715 UpdatePhysicalMassProperties(RawMass); 857 UpdatePhysicalMassProperties(RawMass, false);
716 858
717 // Set collision detection parameters 859 // Set collision detection parameters
718 if (PhysicsScene.Params.ccdMotionThreshold > 0f) 860 if (BSParam.CcdMotionThreshold > 0f)
719 { 861 {
720 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); 862 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
721 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); 863 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
722 } 864 }
723 865
724 // Various values for simulation limits 866 // Various values for simulation limits
725 BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); 867 PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping);
726 BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime); 868 PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime);
727 BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); 869 PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold);
728 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); 870 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
729 871
730 // There might be special things needed for implementing linksets. 872 // This collides like an object.
731 Linkset.MakeDynamic(this); 873 PhysBody.collisionType = CollisionType.Dynamic;
732 874
733 // Force activation of the object so Bullet will act on it. 875 // Force activation of the object so Bullet will act on it.
734 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. 876 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
735 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); 877 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
736 // BulletSimAPI.Activate2(BSBody.ptr, true);
737 878
738 PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter; 879 // There might be special things needed for implementing linksets.
739 PhysBody.collisionMask = CollisionFilterGroups.ObjectMask; 880 Linkset.MakeDynamic(this);
740 } 881 }
741 } 882 }
742 883
@@ -746,7 +887,7 @@ public sealed class BSPrim : BSPhysObject
746 // the functions after this one set up the state of a possibly newly created collision body. 887 // the functions after this one set up the state of a possibly newly created collision body.
747 private void MakeSolid(bool makeSolid) 888 private void MakeSolid(bool makeSolid)
748 { 889 {
749 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr); 890 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody);
750 if (makeSolid) 891 if (makeSolid)
751 { 892 {
752 // Verify the previous code created the correct shape for this type of thing. 893 // Verify the previous code created the correct shape for this type of thing.
@@ -754,7 +895,7 @@ public sealed class BSPrim : BSPhysObject
754 { 895 {
755 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); 896 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
756 } 897 }
757 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 898 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
758 } 899 }
759 else 900 else
760 { 901 {
@@ -762,9 +903,10 @@ public sealed class BSPrim : BSPhysObject
762 { 903 {
763 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 904 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
764 } 905 }
765 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 906 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
766 PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; 907
767 PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; 908 // Change collision info from a static object to a ghosty collision object
909 PhysBody.collisionType = CollisionType.VolumeDetect;
768 } 910 }
769 } 911 }
770 912
@@ -773,8 +915,8 @@ public sealed class BSPrim : BSPhysObject
773 // Called in taint-time!! 915 // Called in taint-time!!
774 private void ActivateIfPhysical(bool forceIt) 916 private void ActivateIfPhysical(bool forceIt)
775 { 917 {
776 if (IsPhysical) 918 if (IsPhysical && PhysBody.HasPhysicalBody)
777 BulletSimAPI.Activate2(PhysBody.ptr, forceIt); 919 PhysicsScene.PE.Activate(PhysBody, forceIt);
778 } 920 }
779 921
780 // Turn on or off the flag controlling whether collision events are returned to the simulator. 922 // Turn on or off the flag controlling whether collision events are returned to the simulator.
@@ -782,11 +924,27 @@ public sealed class BSPrim : BSPhysObject
782 { 924 {
783 if (wantsCollisionEvents) 925 if (wantsCollisionEvents)
784 { 926 {
785 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 927 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
786 } 928 }
787 else 929 else
788 { 930 {
789 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 931 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
932 }
933 }
934
935 // Add me to the physical world.
936 // Object MUST NOT already be in the world.
937 // This routine exists because some assorted properties get mangled by adding to the world.
938 internal void AddObjectToPhysicalWorld()
939 {
940 if (PhysBody.HasPhysicalBody)
941 {
942 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody);
943 }
944 else
945 {
946 m_log.ErrorFormat("{0} Attempt to add physical object without body. id={1}", LogHeader, LocalID);
947 DetailLog("{0},BSPrim.UpdatePhysicalParameters,addObjectWithoutBody,cType={1}", LocalID, PhysBody.collisionType);
790 } 948 }
791 } 949 }
792 950
@@ -805,18 +963,6 @@ public sealed class BSPrim : BSPhysObject
805 get { return _throttleUpdates; } 963 get { return _throttleUpdates; }
806 set { _throttleUpdates = value; } 964 set { _throttleUpdates = value; }
807 } 965 }
808 public override bool IsColliding {
809 get { return (CollidingStep == PhysicsScene.SimulationStep); }
810 set { _isColliding = value; }
811 }
812 public override bool CollidingGround {
813 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
814 set { _collidingGround = value; }
815 }
816 public override bool CollidingObj {
817 get { return _collidingObj; }
818 set { _collidingObj = value; }
819 }
820 public bool IsPhantom { 966 public bool IsPhantom {
821 get { 967 get {
822 // SceneObjectPart removes phantom objects from the physics scene 968 // SceneObjectPart removes phantom objects from the physics scene
@@ -831,32 +977,23 @@ public sealed class BSPrim : BSPhysObject
831 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() 977 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
832 { 978 {
833 if (_floatOnWater) 979 if (_floatOnWater)
834 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); 980 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
835 else 981 else
836 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); 982 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
837 }); 983 });
838 } 984 }
839 } 985 }
840 public override OMV.Vector3 RotationalVelocity { 986 public override OMV.Vector3 RotationalVelocity {
841 get { 987 get {
842 /*
843 OMV.Vector3 pv = OMV.Vector3.Zero;
844 // if close to zero, report zero
845 // This is copied from ODE but I'm not sure why it returns zero but doesn't
846 // zero the property in the physics engine.
847 if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
848 return pv;
849 */
850
851 return _rotationalVelocity; 988 return _rotationalVelocity;
852 } 989 }
853 set { 990 set {
854 _rotationalVelocity = value; 991 _rotationalVelocity = value;
992 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity);
855 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 993 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
856 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 994 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
857 { 995 {
858 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 996 ForceRotationalVelocity = _rotationalVelocity;
859 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
860 }); 997 });
861 } 998 }
862 } 999 }
@@ -866,7 +1003,13 @@ public sealed class BSPrim : BSPhysObject
866 } 1003 }
867 set { 1004 set {
868 _rotationalVelocity = value; 1005 _rotationalVelocity = value;
869 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); 1006 if (PhysBody.HasPhysicalBody)
1007 {
1008 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
1009 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
1010 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
1011 ActivateIfPhysical(false);
1012 }
870 } 1013 }
871 } 1014 }
872 public override bool Kinematic { 1015 public override bool Kinematic {
@@ -890,9 +1033,10 @@ public sealed class BSPrim : BSPhysObject
890 set { 1033 set {
891 _buoyancy = value; 1034 _buoyancy = value;
892 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 1035 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
893 // Buoyancy is faked by changing the gravity applied to the object 1036 // Force the recalculation of the various inertia,etc variables in the object
894 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); 1037 DetailLog("{0},BSPrim.ForceBuoyancy,buoy={1},mass={2}", LocalID, _buoyancy, _mass);
895 BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); 1038 UpdatePhysicalMassProperties(_mass, true);
1039 ActivateIfPhysical(false);
896 } 1040 }
897 } 1041 }
898 1042
@@ -900,17 +1044,112 @@ public sealed class BSPrim : BSPhysObject
900 public override OMV.Vector3 PIDTarget { 1044 public override OMV.Vector3 PIDTarget {
901 set { _PIDTarget = value; } 1045 set { _PIDTarget = value; }
902 } 1046 }
903 public override bool PIDActive {
904 set { _usePID = value; }
905 }
906 public override float PIDTau { 1047 public override float PIDTau {
907 set { _PIDTau = value; } 1048 set { _PIDTau = value; }
908 } 1049 }
1050 public override bool PIDActive {
1051 set {
1052 if (value)
1053 {
1054 // We're taking over after this.
1055 ZeroMotion(true);
1056
1057 _targetMotor = new BSVMotor("BSPrim.PIDTarget",
1058 _PIDTau, // timeScale
1059 BSMotor.Infinite, // decay time scale
1060 BSMotor.InfiniteVector, // friction timescale
1061 1f // efficiency
1062 );
1063 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1064 _targetMotor.SetTarget(_PIDTarget);
1065 _targetMotor.SetCurrent(RawPosition);
1066 /*
1067 _targetMotor = new BSPIDVMotor("BSPrim.PIDTarget");
1068 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1069
1070 _targetMotor.SetTarget(_PIDTarget);
1071 _targetMotor.SetCurrent(RawPosition);
1072 _targetMotor.TimeScale = _PIDTau;
1073 _targetMotor.Efficiency = 1f;
1074 */
1075
1076 RegisterPreStepAction("BSPrim.PIDTarget", LocalID, delegate(float timeStep)
1077 {
1078 if (!IsPhysicallyActive)
1079 {
1080 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID);
1081 return;
1082 }
1083
1084 OMV.Vector3 origPosition = RawPosition; // DEBUG DEBUG (for printout below)
1085
1086 // 'movePosition' is where we'd like the prim to be at this moment.
1087 OMV.Vector3 movePosition = RawPosition + _targetMotor.Step(timeStep);
1088
1089 // If we are very close to our target, turn off the movement motor.
1090 if (_targetMotor.ErrorIsZero())
1091 {
1092 DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}",
1093 LocalID, movePosition, RawPosition, Mass);
1094 ForcePosition = _targetMotor.TargetValue;
1095 _targetMotor.Enabled = false;
1096 }
1097 else
1098 {
1099 ForcePosition = movePosition;
1100 }
1101 DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
1102 });
1103 }
1104 else
1105 {
1106 // Stop any targetting
1107 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID);
1108 }
1109 }
1110 }
909 1111
910 // Used for llSetHoverHeight and maybe vehicle height 1112 // Used for llSetHoverHeight and maybe vehicle height
911 // Hover Height will override MoveTo target's Z 1113 // Hover Height will override MoveTo target's Z
912 public override bool PIDHoverActive { 1114 public override bool PIDHoverActive {
913 set { _useHoverPID = value; } 1115 set {
1116 if (value)
1117 {
1118 // Turning the target on
1119 _hoverMotor = new BSFMotor("BSPrim.Hover",
1120 _PIDHoverTau, // timeScale
1121 BSMotor.Infinite, // decay time scale
1122 BSMotor.Infinite, // friction timescale
1123 1f // efficiency
1124 );
1125 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1126 _hoverMotor.SetCurrent(RawPosition.Z);
1127 _hoverMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1128
1129 RegisterPreStepAction("BSPrim.Hover", LocalID, delegate(float timeStep)
1130 {
1131 if (!IsPhysicallyActive)
1132 return;
1133
1134 _hoverMotor.SetCurrent(RawPosition.Z);
1135 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1136 float targetHeight = _hoverMotor.Step(timeStep);
1137
1138 // 'targetHeight' is where we'd like the Z of the prim to be at this moment.
1139 // Compute the amount of force to push us there.
1140 float moveForce = (targetHeight - RawPosition.Z) * Mass;
1141 // Undo anything the object thinks it's doing at the moment
1142 moveForce = -RawVelocity.Z * Mass;
1143
1144 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, new OMV.Vector3(0f, 0f, moveForce));
1145 DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", LocalID, targetHeight, moveForce, Mass);
1146 });
1147 }
1148 else
1149 {
1150 UnRegisterPreStepAction("BSPrim.Hover", LocalID);
1151 }
1152 }
914 } 1153 }
915 public override float PIDHoverHeight { 1154 public override float PIDHoverHeight {
916 set { _PIDHoverHeight = value; } 1155 set { _PIDHoverHeight = value; }
@@ -919,8 +1158,35 @@ public sealed class BSPrim : BSPhysObject
919 set { _PIDHoverType = value; } 1158 set { _PIDHoverType = value; }
920 } 1159 }
921 public override float PIDHoverTau { 1160 public override float PIDHoverTau {
922 set { _PIDHoverTao = value; } 1161 set { _PIDHoverTau = value; }
923 } 1162 }
1163 // Based on current position, determine what we should be hovering at now.
1164 // Must recompute often. What if we walked offa cliff>
1165 private float ComputeCurrentPIDHoverHeight()
1166 {
1167 float ret = _PIDHoverHeight;
1168 float groundHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
1169
1170 switch (_PIDHoverType)
1171 {
1172 case PIDHoverType.Ground:
1173 ret = groundHeight + _PIDHoverHeight;
1174 break;
1175 case PIDHoverType.GroundAndWater:
1176 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
1177 if (groundHeight > waterHeight)
1178 {
1179 ret = groundHeight + _PIDHoverHeight;
1180 }
1181 else
1182 {
1183 ret = waterHeight + _PIDHoverHeight;
1184 }
1185 break;
1186 }
1187 return ret;
1188 }
1189
924 1190
925 // For RotLookAt 1191 // For RotLookAt
926 public override OMV.Quaternion APIDTarget { set { return; } } 1192 public override OMV.Quaternion APIDTarget { set { return; } }
@@ -928,54 +1194,73 @@ public sealed class BSPrim : BSPhysObject
928 public override float APIDStrength { set { return; } } 1194 public override float APIDStrength { set { return; } }
929 public override float APIDDamping { set { return; } } 1195 public override float APIDDamping { set { return; } }
930 1196
931 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
932 public override void AddForce(OMV.Vector3 force, bool pushforce) { 1197 public override void AddForce(OMV.Vector3 force, bool pushforce) {
933 AddForce(force, pushforce, false); 1198 // Per documentation, max force is limited.
1199 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
1200
1201 // Since this force is being applied in only one step, make this a force per second.
1202 addForce /= PhysicsScene.LastTimeStep;
1203 AddForce(addForce, pushforce, false /* inTaintTime */);
934 } 1204 }
1205
935 // Applying a force just adds this to the total force on the object. 1206 // Applying a force just adds this to the total force on the object.
1207 // This added force will only last the next simulation tick.
936 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 1208 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
937 // for an object, doesn't matter if force is a pushforce or not 1209 // for an object, doesn't matter if force is a pushforce or not
938 if (force.IsFinite()) 1210 if (IsPhysicallyActive)
939 {
940 // _force += force;
941 lock (m_accumulatedForces)
942 m_accumulatedForces.Add(new OMV.Vector3(force));
943 }
944 else
945 {
946 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
947 return;
948 }
949 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
950 { 1211 {
951 OMV.Vector3 fSum = OMV.Vector3.Zero; 1212 if (force.IsFinite())
952 lock (m_accumulatedForces)
953 { 1213 {
954 // Sum the accumulated additional forces for one big force to apply once. 1214 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
955 foreach (OMV.Vector3 v in m_accumulatedForces) 1215
1216 OMV.Vector3 addForce = force;
1217 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
956 { 1218 {
957 fSum += v; 1219 // Bullet adds this central force to the total force for this tick
958 } 1220 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
959 m_accumulatedForces.Clear(); 1221 if (PhysBody.HasPhysicalBody)
1222 {
1223 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce);
1224 ActivateIfPhysical(false);
1225 }
1226 });
960 } 1227 }
961 DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); 1228 else
962 if (fSum != OMV.Vector3.Zero) 1229 {
963 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); 1230 m_log.WarnFormat("{0}: AddForce: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
964 }); 1231 return;
1232 }
1233 }
965 } 1234 }
966 1235
967 // An impulse force is scaled by the mass of the object. 1236 public void AddForceImpulse(OMV.Vector3 impulse, bool pushforce, bool inTaintTime) {
968 public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime) 1237 // for an object, doesn't matter if force is a pushforce or not
969 { 1238 if (!IsPhysicallyActive)
970 OMV.Vector3 applyImpulse = impulse;
971 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate()
972 { 1239 {
973 DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse); 1240 if (impulse.IsFinite())
974 BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse); 1241 {
975 }); 1242 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude);
1243 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
1244
1245 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate()
1246 {
1247 // Bullet adds this impulse immediately to the velocity
1248 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
1249 if (PhysBody.HasPhysicalBody)
1250 {
1251 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse);
1252 ActivateIfPhysical(false);
1253 }
1254 });
1255 }
1256 else
1257 {
1258 m_log.WarnFormat("{0}: AddForceImpulse: Got a NaN impulse applied to a prim. LocalID={1}", LogHeader, LocalID);
1259 return;
1260 }
1261 }
976 } 1262 }
977 1263
978 private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>();
979 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 1264 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
980 AddAngularForce(force, pushforce, false); 1265 AddAngularForce(force, pushforce, false);
981 } 1266 }
@@ -983,42 +1268,37 @@ public sealed class BSPrim : BSPhysObject
983 { 1268 {
984 if (force.IsFinite()) 1269 if (force.IsFinite())
985 { 1270 {
986 // _force += force; 1271 OMV.Vector3 angForce = force;
987 lock (m_accumulatedAngularForces) 1272 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
988 m_accumulatedAngularForces.Add(new OMV.Vector3(force)); 1273 {
1274 if (PhysBody.HasPhysicalBody)
1275 {
1276 PhysicsScene.PE.ApplyTorque(PhysBody, angForce);
1277 ActivateIfPhysical(false);
1278 }
1279 });
989 } 1280 }
990 else 1281 else
991 { 1282 {
992 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 1283 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
993 return; 1284 return;
994 } 1285 }
995 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
996 {
997 OMV.Vector3 fSum = OMV.Vector3.Zero;
998 lock (m_accumulatedAngularForces)
999 {
1000 // Sum the accumulated additional forces for one big force to apply once.
1001 foreach (OMV.Vector3 v in m_accumulatedAngularForces)
1002 {
1003 fSum += v;
1004 }
1005 m_accumulatedAngularForces.Clear();
1006 }
1007 DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
1008 if (fSum != OMV.Vector3.Zero)
1009 {
1010 BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
1011 _torque = fSum;
1012 }
1013 });
1014 } 1286 }
1287
1015 // A torque impulse. 1288 // A torque impulse.
1289 // ApplyTorqueImpulse adds torque directly to the angularVelocity.
1290 // AddAngularForce accumulates the force and applied it to the angular velocity all at once.
1291 // Computed as: angularVelocity += impulse * inertia;
1016 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 1292 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1017 { 1293 {
1018 OMV.Vector3 applyImpulse = impulse; 1294 OMV.Vector3 applyImpulse = impulse;
1019 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() 1295 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1020 { 1296 {
1021 BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); 1297 if (PhysBody.HasPhysicalBody)
1298 {
1299 PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse);
1300 ActivateIfPhysical(false);
1301 }
1022 }); 1302 });
1023 } 1303 }
1024 1304
@@ -1313,11 +1593,7 @@ public sealed class BSPrim : BSPhysObject
1313 } 1593 }
1314 */ 1594 */
1315 1595
1316 if (returnMass <= 0) 1596 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass);
1317 returnMass = 0.0001f;
1318
1319 if (returnMass > PhysicsScene.MaximumObjectMass)
1320 returnMass = PhysicsScene.MaximumObjectMass;
1321 1597
1322 return returnMass; 1598 return returnMass;
1323 }// end CalculateMass 1599 }// end CalculateMass
@@ -1326,37 +1602,20 @@ public sealed class BSPrim : BSPhysObject
1326 // Rebuild the geometry and object. 1602 // Rebuild the geometry and object.
1327 // This is called when the shape changes so we need to recreate the mesh/hull. 1603 // This is called when the shape changes so we need to recreate the mesh/hull.
1328 // Called at taint-time!!! 1604 // Called at taint-time!!!
1329 private void CreateGeomAndObject(bool forceRebuild) 1605 public void CreateGeomAndObject(bool forceRebuild)
1330 { 1606 {
1331 // If this prim is part of a linkset, we must remove and restore the physical
1332 // links if the body is rebuilt.
1333 bool needToRestoreLinkset = false;
1334 bool needToRestoreVehicle = false;
1335
1336 // Create the correct physical representation for this type of object. 1607 // Create the correct physical representation for this type of object.
1337 // Updates PhysBody and PhysShape with the new information. 1608 // Updates base.PhysBody and base.PhysShape with the new information.
1338 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. 1609 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
1339 // Returns 'true' if either the body or the shape was changed. 1610 PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody)
1340 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
1341 { 1611 {
1342 // Called if the current prim body is about to be destroyed. 1612 // Called if the current prim body is about to be destroyed.
1343 // Remove all the physical dependencies on the old body. 1613 // Remove all the physical dependencies on the old body.
1344 // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) 1614 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
1345 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); 1615 Linkset.RemoveBodyDependencies(this);
1346 needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this); 1616 VehicleController.RemoveBodyDependencies(this);
1347 }); 1617 });
1348 1618
1349 if (needToRestoreLinkset)
1350 {
1351 // If physical body dependencies were removed, restore them
1352 Linkset.RestoreBodyDependencies(this);
1353 }
1354 if (needToRestoreVehicle)
1355 {
1356 // If physical body dependencies were removed, restore them
1357 _vehicle.RestoreBodyDependencies(this);
1358 }
1359
1360 // Make sure the properties are set on the new object 1619 // Make sure the properties are set on the new object
1361 UpdatePhysicalParameters(); 1620 UpdatePhysicalParameters();
1362 return; 1621 return;
@@ -1364,95 +1623,53 @@ public sealed class BSPrim : BSPhysObject
1364 1623
1365 // The physics engine says that properties have updated. Update same and inform 1624 // The physics engine says that properties have updated. Update same and inform
1366 // the world that things have changed. 1625 // the world that things have changed.
1367 // TODO: do we really need to check for changed? Maybe just copy values and call RequestPhysicsterseUpdate()
1368 enum UpdatedProperties {
1369 Position = 1 << 0,
1370 Rotation = 1 << 1,
1371 Velocity = 1 << 2,
1372 Acceleration = 1 << 3,
1373 RotationalVel = 1 << 4
1374 }
1375
1376 const float ROTATION_TOLERANCE = 0.01f;
1377 const float VELOCITY_TOLERANCE = 0.001f;
1378 const float POSITION_TOLERANCE = 0.05f;
1379 const float ACCELERATION_TOLERANCE = 0.01f;
1380 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1381
1382 public override void UpdateProperties(EntityProperties entprop) 1626 public override void UpdateProperties(EntityProperties entprop)
1383 { 1627 {
1384 /* 1628 // Updates only for individual prims and for the root object of a linkset.
1385 UpdatedProperties changed = 0; 1629 if (Linkset.IsRoot(this))
1386 // assign to the local variables so the normal set action does not happen
1387 // if (_position != entprop.Position)
1388 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1389 {
1390 _position = entprop.Position;
1391 changed |= UpdatedProperties.Position;
1392 }
1393 // if (_orientation != entprop.Rotation)
1394 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1395 {
1396 _orientation = entprop.Rotation;
1397 changed |= UpdatedProperties.Rotation;
1398 }
1399 // if (_velocity != entprop.Velocity)
1400 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1401 {
1402 _velocity = entprop.Velocity;
1403 changed |= UpdatedProperties.Velocity;
1404 }
1405 // if (_acceleration != entprop.Acceleration)
1406 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1407 {
1408 _acceleration = entprop.Acceleration;
1409 changed |= UpdatedProperties.Acceleration;
1410 }
1411 // if (_rotationalVelocity != entprop.RotationalVelocity)
1412 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1413 {
1414 _rotationalVelocity = entprop.RotationalVelocity;
1415 changed |= UpdatedProperties.RotationalVel;
1416 }
1417 if (changed != 0)
1418 { 1630 {
1419 // Only update the position of single objects and linkset roots 1631 // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
1420 if (Linkset.IsRoot(this)) 1632 // TODO: handle physics introduced by Bullet with computed vehicle physics.
1633 if (VehicleController.IsActive)
1421 { 1634 {
1422 base.RequestPhysicsterseUpdate(); 1635 entprop.RotationalVelocity = OMV.Vector3.Zero;
1423 } 1636 }
1424 }
1425 */
1426 1637
1427 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1638 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
1428 1639
1429 // Updates only for individual prims and for the root object of a linkset. 1640 // Undo any center-of-mass displacement that might have been done.
1430 if (Linkset.IsRoot(this)) 1641 if (PositionDisplacement != OMV.Vector3.Zero)
1431 { 1642 {
1432 // Assign directly to the local variables so the normal set action does not happen 1643 // Correct for any rotation around the center-of-mass
1644 // TODO!!!
1645 entprop.Position -= PositionDisplacement;
1646 }
1647
1648 // Assign directly to the local variables so the normal set actions do not happen
1433 _position = entprop.Position; 1649 _position = entprop.Position;
1434 _orientation = entprop.Rotation; 1650 _orientation = entprop.Rotation;
1435 _velocity = entprop.Velocity; 1651 _velocity = entprop.Velocity;
1436 _acceleration = entprop.Acceleration; 1652 _acceleration = entprop.Acceleration;
1437 _rotationalVelocity = entprop.RotationalVelocity; 1653 _rotationalVelocity = entprop.RotationalVelocity;
1438 1654
1655 // DetailLog("{0},BSPrim.UpdateProperties,afterAssign,entprop={1}", LocalID, entprop); // DEBUG DEBUG
1656
1439 // The sanity check can change the velocity and/or position. 1657 // The sanity check can change the velocity and/or position.
1440 if (PositionSanityCheck(true)) 1658 if (PositionSanityCheck(true /* inTaintTime */ ))
1441 { 1659 {
1442 entprop.Position = _position; 1660 entprop.Position = _position;
1443 entprop.Velocity = _velocity; 1661 entprop.Velocity = _velocity;
1662 entprop.RotationalVelocity = _rotationalVelocity;
1663 entprop.Acceleration = _acceleration;
1444 } 1664 }
1445 1665
1666 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG
1667 DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction);
1668
1446 // remember the current and last set values 1669 // remember the current and last set values
1447 LastEntityProperties = CurrentEntityProperties; 1670 LastEntityProperties = CurrentEntityProperties;
1448 CurrentEntityProperties = entprop; 1671 CurrentEntityProperties = entprop;
1449 1672
1450 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
1451 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1452 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
1453
1454 // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
1455
1456 base.RequestPhysicsterseUpdate(); 1673 base.RequestPhysicsterseUpdate();
1457 } 1674 }
1458 /* 1675 /*
@@ -1466,7 +1683,7 @@ public sealed class BSPrim : BSPhysObject
1466 */ 1683 */
1467 1684
1468 // The linkset implimentation might want to know about this. 1685 // The linkset implimentation might want to know about this.
1469 Linkset.UpdateProperties(this); 1686 Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
1470 } 1687 }
1471} 1688}
1472} 1689}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 27a78d1..f8a0c1e 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -26,6 +26,8 @@
26 */ 26 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Linq;
30using System.Reflection;
29using System.Runtime.InteropServices; 31using System.Runtime.InteropServices;
30using System.Text; 32using System.Text;
31using System.Threading; 33using System.Threading;
@@ -38,40 +40,22 @@ using Nini.Config;
38using log4net; 40using log4net;
39using OpenMetaverse; 41using OpenMetaverse;
40 42
41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
42// Test sculpties (verified that they don't work)
43// Compute physics FPS reasonably
44// Based on material, set density and friction
45// Don't use constraints in linksets of non-physical objects. Means having to move children manually.
46// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
47// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
48// At the moment, physical and phantom causes object to drop through the terrain
49// Physical phantom objects and related typing (collision options )
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
53// Should prim.link() and prim.delink() membership checking happen at taint time?
54// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once.
55// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
56// Implement LockAngularMotion
57// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
58// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
59// Add PID movement operations. What does ScenePresence.MoveToTarget do?
60// Check terrain size. 128 or 127?
61// Raycast
62//
63namespace OpenSim.Region.Physics.BulletSPlugin 43namespace OpenSim.Region.Physics.BulletSPlugin
64{ 44{
65public sealed class BSScene : PhysicsScene, IPhysicsParameters 45public sealed class BSScene : PhysicsScene, IPhysicsParameters
66{ 46{
67 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 47 internal static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
68 private static readonly string LogHeader = "[BULLETS SCENE]"; 48 internal static readonly string LogHeader = "[BULLETS SCENE]";
69 49
70 // The name of the region we're working for. 50 // The name of the region we're working for.
71 public string RegionName { get; private set; } 51 public string RegionName { get; private set; }
72 52
73 public string BulletSimVersion = "?"; 53 public string BulletSimVersion = "?";
74 54
55 // The handle to the underlying managed or unmanaged version of Bullet being used.
56 public string BulletEngineName { get; private set; }
57 public BSAPITemplate PE;
58
75 public Dictionary<uint, BSPhysObject> PhysObjects; 59 public Dictionary<uint, BSPhysObject> PhysObjects;
76 public BSShapeCollection Shapes; 60 public BSShapeCollection Shapes;
77 61
@@ -82,32 +66,29 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
82 // every tick so OpenSim will update its animation. 66 // every tick so OpenSim will update its animation.
83 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>(); 67 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
84 68
85 // List of all the objects that have vehicle properties and should be called
86 // to update each physics step.
87 private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
88
89 // let my minuions use my logger 69 // let my minuions use my logger
90 public ILog Logger { get { return m_log; } } 70 public ILog Logger { get { return m_log; } }
91 71
92 public IMesher mesher; 72 public IMesher mesher;
93 // Level of Detail values kept as float because that's what the Meshmerizer wants
94 public float MeshLOD { get; private set; }
95 public float MeshMegaPrimLOD { get; private set; }
96 public float MeshMegaPrimThreshold { get; private set; }
97 public float SculptLOD { get; private set; }
98
99 public uint WorldID { get; private set; } 73 public uint WorldID { get; private set; }
100 public BulletSim World { get; private set; } 74 public BulletWorld World { get; private set; }
101 75
102 // All the constraints that have been allocated in this instance. 76 // All the constraints that have been allocated in this instance.
103 public BSConstraintCollection Constraints { get; private set; } 77 public BSConstraintCollection Constraints { get; private set; }
104 78
105 // Simulation parameters 79 // Simulation parameters
106 private int m_maxSubSteps; 80 internal int m_maxSubSteps;
107 private float m_fixedTimeStep; 81 internal float m_fixedTimeStep;
108 private long m_simulationStep = 0; 82 internal long m_simulationStep = 0;
83 internal float NominalFrameRate { get; set; }
109 public long SimulationStep { get { return m_simulationStep; } } 84 public long SimulationStep { get { return m_simulationStep; } }
110 private int m_taintsToProcessPerStep; 85 internal float LastTimeStep { get; private set; }
86
87 // Physical objects can register for prestep or poststep events
88 public delegate void PreStepAction(float timeStep);
89 public delegate void PostStepAction(float timeStep);
90 public event PreStepAction BeforeStep;
91 public event PostStepAction AfterStep;
111 92
112 // A value of the time now so all the collision and update routines do not have to get their own 93 // A value of the time now so all the collision and update routines do not have to get their own
113 // Set to 'now' just before all the prims and actors are called for collisions and updates 94 // Set to 'now' just before all the prims and actors are called for collisions and updates
@@ -121,31 +102,22 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
121 public bool InTaintTime { get; private set; } 102 public bool InTaintTime { get; private set; }
122 103
123 // Pinned memory used to pass step information between managed and unmanaged 104 // Pinned memory used to pass step information between managed and unmanaged
124 private int m_maxCollisionsPerFrame; 105 internal int m_maxCollisionsPerFrame;
125 private CollisionDesc[] m_collisionArray; 106 internal CollisionDesc[] m_collisionArray;
126 private GCHandle m_collisionArrayPinnedHandle;
127 107
128 private int m_maxUpdatesPerFrame; 108 internal int m_maxUpdatesPerFrame;
129 private EntityProperties[] m_updateArray; 109 internal EntityProperties[] m_updateArray;
130 private GCHandle m_updateArrayPinnedHandle;
131
132 public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
133 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
134 public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
135
136 public float PID_D { get; private set; } // derivative
137 public float PID_P { get; private set; } // proportional
138 110
139 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 111 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
140 public const uint GROUNDPLANE_ID = 1; 112 public const uint GROUNDPLANE_ID = 1;
141 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here 113 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
142 114
143 private float m_waterLevel; 115 public float SimpleWaterLevel { get; set; }
144 public BSTerrainManager TerrainManager { get; private set; } 116 public BSTerrainManager TerrainManager { get; private set; }
145 117
146 public ConfigurationParameters Params 118 public ConfigurationParameters Params
147 { 119 {
148 get { return m_params[0]; } 120 get { return UnmanagedParams[0]; }
149 } 121 }
150 public Vector3 DefaultGravity 122 public Vector3 DefaultGravity
151 { 123 {
@@ -157,8 +129,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
157 get { return Params.gravity; } 129 get { return Params.gravity; }
158 } 130 }
159 131
160 public float MaximumObjectMass { get; private set; }
161
162 // When functions in the unmanaged code must be called, it is only 132 // When functions in the unmanaged code must be called, it is only
163 // done at a known time just before the simulation step. The taint 133 // done at a known time just before the simulation step. The taint
164 // system saves all these function calls and executes them in 134 // system saves all these function calls and executes them in
@@ -181,13 +151,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
181 151
182 // A pointer to an instance if this structure is passed to the C++ code 152 // A pointer to an instance if this structure is passed to the C++ code
183 // Used to pass basic configuration values to the unmanaged code. 153 // Used to pass basic configuration values to the unmanaged code.
184 ConfigurationParameters[] m_params; 154 internal ConfigurationParameters[] UnmanagedParams;
185 GCHandle m_paramsHandle;
186
187 // Handle to the callback used by the unmanaged code to call into the managed code.
188 // Used for debug logging.
189 // Need to store the handle in a persistant variable so it won't be freed.
190 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
191 155
192 // Sometimes you just have to log everything. 156 // Sometimes you just have to log everything.
193 public Logging.LogWriter PhysicsLogging; 157 public Logging.LogWriter PhysicsLogging;
@@ -195,15 +159,24 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
195 private string m_physicsLoggingDir; 159 private string m_physicsLoggingDir;
196 private string m_physicsLoggingPrefix; 160 private string m_physicsLoggingPrefix;
197 private int m_physicsLoggingFileMinutes; 161 private int m_physicsLoggingFileMinutes;
162 private bool m_physicsLoggingDoFlush;
163 private bool m_physicsPhysicalDumpEnabled;
164 public float PhysicsMetricDumpFrames { get; set; }
198 // 'true' of the vehicle code is to log lots of details 165 // 'true' of the vehicle code is to log lots of details
199 public bool VehicleLoggingEnabled { get; private set; } 166 public bool VehicleLoggingEnabled { get; private set; }
167 public bool VehiclePhysicalLoggingEnabled { get; private set; }
200 168
201 #region Construction and Initialization 169 #region Construction and Initialization
202 public BSScene(string identifier) 170 public BSScene(string engineType, string identifier)
203 { 171 {
204 m_initialized = false; 172 m_initialized = false;
205 // we are passed the name of the region we're working for. 173
174 // The name of the region we're working for is passed to us. Keep for identification.
206 RegionName = identifier; 175 RegionName = identifier;
176
177 // Set identifying variables in the PhysicsScene interface.
178 EngineType = engineType;
179 Name = EngineType + "/" + RegionName;
207 } 180 }
208 181
209 public override void Initialise(IMesher meshmerizer, IConfigSource config) 182 public override void Initialise(IMesher meshmerizer, IConfigSource config)
@@ -216,17 +189,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
216 Shapes = new BSShapeCollection(this); 189 Shapes = new BSShapeCollection(this);
217 190
218 // Allocate pinned memory to pass parameters. 191 // Allocate pinned memory to pass parameters.
219 m_params = new ConfigurationParameters[1]; 192 UnmanagedParams = new ConfigurationParameters[1];
220 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned);
221 193
222 // Set default values for physics parameters plus any overrides from the ini file 194 // Set default values for physics parameters plus any overrides from the ini file
223 GetInitialParameterValues(config); 195 GetInitialParameterValues(config);
224 196
225 // allocate more pinned memory close to the above in an attempt to get the memory all together 197 // Get the connection to the physics engine (could be native or one of many DLLs)
226 m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame]; 198 PE = SelectUnderlyingBulletEngine(BulletEngineName);
227 m_collisionArrayPinnedHandle = GCHandle.Alloc(m_collisionArray, GCHandleType.Pinned);
228 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
229 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
230 199
231 // Enable very detailed logging. 200 // Enable very detailed logging.
232 // By creating an empty logger when not logging, the log message invocation code 201 // By creating an empty logger when not logging, the log message invocation code
@@ -234,28 +203,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
234 if (m_physicsLoggingEnabled) 203 if (m_physicsLoggingEnabled)
235 { 204 {
236 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); 205 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
206 PhysicsLogging.ErrorLogger = m_log; // for DEBUG. Let's the logger output error messages.
237 } 207 }
238 else 208 else
239 { 209 {
240 PhysicsLogging = new Logging.LogWriter(); 210 PhysicsLogging = new Logging.LogWriter();
241 } 211 }
242 212
243 // If Debug logging level, enable logging from the unmanaged code 213 // Allocate memory for returning of the updates and collisions from the physics engine
244 m_DebugLogCallbackHandle = null; 214 m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame];
245 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) 215 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
246 {
247 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
248 if (PhysicsLogging.Enabled)
249 // The handle is saved in a variable to make sure it doesn't get freed after this call
250 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
251 else
252 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
253 }
254
255 // Get the version of the DLL
256 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
257 // BulletSimVersion = BulletSimAPI.GetVersion();
258 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
259 216
260 // The bounding box for the simulated world. The origin is 0,0,0 unless we're 217 // The bounding box for the simulated world. The origin is 0,0,0 unless we're
261 // a child in a mega-region. 218 // a child in a mega-region.
@@ -263,18 +220,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
263 // area. It tracks active objects no matter where they are. 220 // area. It tracks active objects no matter where they are.
264 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 221 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
265 222
266 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 223 World = PE.Initialize(worldExtent, Params, m_maxCollisionsPerFrame, ref m_collisionArray, m_maxUpdatesPerFrame, ref m_updateArray);
267 World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
268 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
269 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
270 m_DebugLogCallbackHandle));
271 224
272 Constraints = new BSConstraintCollection(World); 225 Constraints = new BSConstraintCollection(World);
273 226
274 TerrainManager = new BSTerrainManager(this); 227 TerrainManager = new BSTerrainManager(this);
275 TerrainManager.CreateInitialGroundPlaneAndTerrain(); 228 TerrainManager.CreateInitialGroundPlaneAndTerrain();
276 229
277 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation); 230 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation);
278 231
279 InTaintTime = false; 232 InTaintTime = false;
280 m_initialized = true; 233 m_initialized = true;
@@ -285,9 +238,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
285 private void GetInitialParameterValues(IConfigSource config) 238 private void GetInitialParameterValues(IConfigSource config)
286 { 239 {
287 ConfigurationParameters parms = new ConfigurationParameters(); 240 ConfigurationParameters parms = new ConfigurationParameters();
288 m_params[0] = parms; 241 UnmanagedParams[0] = parms;
289 242
290 SetParameterDefaultValues(); 243 BSParam.SetParameterDefaultValues(this);
291 244
292 if (config != null) 245 if (config != null)
293 { 246 {
@@ -295,19 +248,34 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
295 IConfig pConfig = config.Configs["BulletSim"]; 248 IConfig pConfig = config.Configs["BulletSim"];
296 if (pConfig != null) 249 if (pConfig != null)
297 { 250 {
298 SetParameterConfigurationValues(pConfig); 251 BSParam.SetParameterConfigurationValues(this, pConfig);
252
253 // There are two Bullet implementations to choose from
254 BulletEngineName = pConfig.GetString("BulletEngine", "BulletUnmanaged");
299 255
300 // Very detailed logging for physics debugging 256 // Very detailed logging for physics debugging
257 // TODO: the boolean values can be moved to the normal parameter processing.
301 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 258 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
302 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); 259 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
303 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); 260 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
304 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); 261 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
262 m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
263 m_physicsPhysicalDumpEnabled = pConfig.GetBoolean("PhysicsPhysicalDumpEnabled", false);
305 // Very detailed logging for vehicle debugging 264 // Very detailed logging for vehicle debugging
306 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 265 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
266 VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false);
307 267
308 // Do any replacements in the parameters 268 // Do any replacements in the parameters
309 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); 269 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
310 } 270 }
271
272 // The material characteristics.
273 BSMaterials.InitializeFromDefaults(Params);
274 if (pConfig != null)
275 {
276 // Let the user add new and interesting material property values.
277 BSMaterials.InitializefromParameters(pConfig);
278 }
311 } 279 }
312 } 280 }
313 281
@@ -326,16 +294,41 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
326 return ret; 294 return ret;
327 } 295 }
328 296
329 // Called directly from unmanaged code so don't do much 297 // Select the connection to the actual Bullet implementation.
330 private void BulletLogger(string msg) 298 // The main engine selection is the engineName up to the first hypen.
299 // So "Bullet-2.80-OpenCL-Intel" specifies the 'bullet' class here and the whole name
300 // is passed to the engine to do its special selection, etc.
301 private BSAPITemplate SelectUnderlyingBulletEngine(string engineName)
331 { 302 {
332 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 303 // For the moment, do a simple switch statement.
333 } 304 // Someday do fancyness with looking up the interfaces in the assembly.
305 BSAPITemplate ret = null;
334 306
335 // Called directly from unmanaged code so don't do much 307 string selectionName = engineName.ToLower();
336 private void BulletLoggerPhysLog(string msg) 308 int hyphenIndex = engineName.IndexOf("-");
337 { 309 if (hyphenIndex > 0)
338 DetailLog("[BULLETS UNMANAGED]:" + msg); 310 selectionName = engineName.ToLower().Substring(0, hyphenIndex - 1);
311
312 switch (selectionName)
313 {
314 case "bulletunmanaged":
315 ret = new BSAPIUnman(engineName, this);
316 break;
317 case "bulletxna":
318 ret = new BSAPIXNA(engineName, this);
319 break;
320 }
321
322 if (ret == null)
323 {
324 m_log.ErrorFormat("{0) COULD NOT SELECT BULLET ENGINE: '[BulletSim]PhysicsEngine' must be either 'BulletUnmanaged-*' or 'BulletXNA-*'", LogHeader);
325 }
326 else
327 {
328 m_log.WarnFormat("{0} Selected bullet engine {1} -> {2}/{3}", LogHeader, engineName, ret.BulletEngineName, ret.BulletEngineVersion);
329 }
330
331 return ret;
339 } 332 }
340 333
341 public override void Dispose() 334 public override void Dispose()
@@ -345,8 +338,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
345 // make sure no stepping happens while we're deleting stuff 338 // make sure no stepping happens while we're deleting stuff
346 m_initialized = false; 339 m_initialized = false;
347 340
348 TerrainManager.ReleaseGroundPlaneAndTerrain();
349
350 foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects) 341 foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
351 { 342 {
352 kvp.Value.Destroy(); 343 kvp.Value.Destroy();
@@ -366,8 +357,15 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
366 Shapes = null; 357 Shapes = null;
367 } 358 }
368 359
360 if (TerrainManager != null)
361 {
362 TerrainManager.ReleaseGroundPlaneAndTerrain();
363 TerrainManager.Dispose();
364 TerrainManager = null;
365 }
366
369 // Anything left in the unmanaged code should be cleaned out 367 // Anything left in the unmanaged code should be cleaned out
370 BulletSimAPI.Shutdown2(World.ptr); 368 PE.Shutdown(World);
371 369
372 // Not logging any more 370 // Not logging any more
373 PhysicsLogging.Close(); 371 PhysicsLogging.Close();
@@ -389,12 +387,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
389 if (!m_initialized) return null; 387 if (!m_initialized) return null;
390 388
391 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); 389 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
392 lock (PhysObjects) PhysObjects.Add(localID, actor); 390 lock (PhysObjects)
391 PhysObjects.Add(localID, actor);
393 392
394 // TODO: Remove kludge someday. 393 // TODO: Remove kludge someday.
395 // We must generate a collision for avatars whether they collide or not. 394 // We must generate a collision for avatars whether they collide or not.
396 // This is required by OpenSim to update avatar animations, etc. 395 // This is required by OpenSim to update avatar animations, etc.
397 lock (m_avatars) m_avatars.Add(actor); 396 lock (m_avatars)
397 m_avatars.Add(actor);
398 398
399 return actor; 399 return actor;
400 } 400 }
@@ -410,9 +410,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
410 { 410 {
411 try 411 try
412 { 412 {
413 lock (PhysObjects) PhysObjects.Remove(actor.LocalID); 413 lock (PhysObjects)
414 PhysObjects.Remove(bsactor.LocalID);
414 // Remove kludge someday 415 // Remove kludge someday
415 lock (m_avatars) m_avatars.Remove(bsactor); 416 lock (m_avatars)
417 m_avatars.Remove(bsactor);
416 } 418 }
417 catch (Exception e) 419 catch (Exception e)
418 { 420 {
@@ -421,6 +423,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
421 bsactor.Destroy(); 423 bsactor.Destroy();
422 // bsactor.dispose(); 424 // bsactor.dispose();
423 } 425 }
426 else
427 {
428 m_log.ErrorFormat("{0}: Requested to remove avatar that is not a BSCharacter. ID={1}, type={2}",
429 LogHeader, actor.LocalID, actor.GetType().Name);
430 }
424 } 431 }
425 432
426 public override void RemovePrim(PhysicsActor prim) 433 public override void RemovePrim(PhysicsActor prim)
@@ -474,41 +481,56 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
474 // Simulate one timestep 481 // Simulate one timestep
475 public override float Simulate(float timeStep) 482 public override float Simulate(float timeStep)
476 { 483 {
484 // prevent simulation until we've been initialized
485 if (!m_initialized) return 5.0f;
486
487 LastTimeStep = timeStep;
488
477 int updatedEntityCount = 0; 489 int updatedEntityCount = 0;
478 IntPtr updatedEntitiesPtr;
479 int collidersCount = 0; 490 int collidersCount = 0;
480 IntPtr collidersPtr;
481 491
482 int beforeTime = 0; 492 int beforeTime = 0;
483 int simTime = 0; 493 int simTime = 0;
484 494
485 // prevent simulation until we've been initialized
486 if (!m_initialized) return 5.0f;
487
488 // update the prim states while we know the physics engine is not busy 495 // update the prim states while we know the physics engine is not busy
489 int numTaints = _taintOperations.Count; 496 int numTaints = _taintOperations.Count;
497
498 InTaintTime = true; // Only used for debugging so locking is not necessary.
499
500 ProcessTaints();
501
502 // Some of the physical objects requre individual, pre-step calls
503 // (vehicles and avatar movement, in particular)
504 TriggerPreStepEvent(timeStep);
505
506 // the prestep actions might have added taints
507 numTaints += _taintOperations.Count;
490 ProcessTaints(); 508 ProcessTaints();
491 509
492 // Some of the prims operate with special vehicle properties 510 InTaintTime = false; // Only used for debugging so locking is not necessary.
493 ProcessVehicles(timeStep); 511
494 ProcessTaints(); // the vehicles might have added taints 512 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
513 // Only enable this in a limited test world with few objects.
514 if (m_physicsPhysicalDumpEnabled)
515 PE.DumpAllInfo(World);
495 516
496 // step the physical world one interval 517 // step the physical world one interval
497 m_simulationStep++; 518 m_simulationStep++;
498 int numSubSteps = 0; 519 int numSubSteps = 0;
499
500 try 520 try
501 { 521 {
502 if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG 522 if (PhysicsLogging.Enabled)
503 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); 523 beforeTime = Util.EnvironmentTickCount();
504 524
505 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, 525 numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);
506 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
507 526
508 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); 527 if (PhysicsLogging.Enabled)
509 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", 528 {
510 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); 529 simTime = Util.EnvironmentTickCountSubtract(beforeTime);
511 if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG 530 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
531 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
532 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
533 }
512 } 534 }
513 catch (Exception e) 535 catch (Exception e)
514 { 536 {
@@ -520,9 +542,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
520 collidersCount = 0; 542 collidersCount = 0;
521 } 543 }
522 544
523 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in 545 if ((m_simulationStep % PhysicsMetricDumpFrames) == 0)
546 PE.DumpPhysicsStatistics(World);
524 547
525 // Get a value for 'now' so all the collision and update routines don't have to get their own 548 // Get a value for 'now' so all the collision and update routines don't have to get their own.
526 SimulationNowTime = Util.EnvironmentTickCount(); 549 SimulationNowTime = Util.EnvironmentTickCount();
527 550
528 // If there were collisions, process them by sending the event to the prim. 551 // If there were collisions, process them by sending the event to the prim.
@@ -535,8 +558,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
535 uint cB = m_collisionArray[ii].bID; 558 uint cB = m_collisionArray[ii].bID;
536 Vector3 point = m_collisionArray[ii].point; 559 Vector3 point = m_collisionArray[ii].point;
537 Vector3 normal = m_collisionArray[ii].normal; 560 Vector3 normal = m_collisionArray[ii].normal;
538 SendCollision(cA, cB, point, normal, 0.01f); 561 float penetration = m_collisionArray[ii].penetration;
539 SendCollision(cB, cA, point, -normal, 0.01f); 562 SendCollision(cA, cB, point, normal, penetration);
563 SendCollision(cB, cA, point, -normal, penetration);
540 } 564 }
541 } 565 }
542 566
@@ -562,12 +586,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
562 586
563 // Objects that are done colliding are removed from the ObjectsWithCollisions list. 587 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
564 // Not done above because it is inside an iteration of ObjectWithCollisions. 588 // Not done above because it is inside an iteration of ObjectWithCollisions.
589 // This complex collision processing is required to create an empty collision
590 // event call after all real collisions have happened on an object. This enables
591 // the simulator to generate the 'collision end' event.
565 if (ObjectsWithNoMoreCollisions.Count > 0) 592 if (ObjectsWithNoMoreCollisions.Count > 0)
566 { 593 {
567 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) 594 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
568 ObjectsWithCollisions.Remove(po); 595 ObjectsWithCollisions.Remove(po);
569 ObjectsWithNoMoreCollisions.Clear(); 596 ObjectsWithNoMoreCollisions.Clear();
570 } 597 }
598 // Done with collisions.
571 599
572 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 600 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
573 if (updatedEntityCount > 0) 601 if (updatedEntityCount > 0)
@@ -583,17 +611,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
583 } 611 }
584 } 612 }
585 613
586 ProcessPostStepTaints(); 614 TriggerPostStepEvent(timeStep);
587 615
588 // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. 616 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
589 // Only enable this in a limited test world with few objects. 617 // Only enable this in a limited test world with few objects.
590 // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG 618 if (m_physicsPhysicalDumpEnabled)
619 PE.DumpAllInfo(World);
591 620
592 // The physics engine returns the number of milliseconds it simulated this call. 621 // The physics engine returns the number of milliseconds it simulated this call.
593 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 622 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
594 // We multiply by 55 to give a recognizable running rate (55 or less). 623 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55).
595 return numSubSteps * m_fixedTimeStep * 1000 * 55; 624 return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
596 // return timeStep * 1000 * 55;
597 } 625 }
598 626
599 // Something has collided 627 // Something has collided
@@ -639,12 +667,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
639 667
640 public override void SetWaterLevel(float baseheight) 668 public override void SetWaterLevel(float baseheight)
641 { 669 {
642 m_waterLevel = baseheight; 670 SimpleWaterLevel = baseheight;
643 }
644 // Someday....
645 public float GetWaterLevelAtXYZ(Vector3 loc)
646 {
647 return m_waterLevel;
648 } 671 }
649 672
650 public override void DeleteTerrain() 673 public override void DeleteTerrain()
@@ -675,12 +698,35 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
675 698
676 public override Dictionary<uint, float> GetTopColliders() 699 public override Dictionary<uint, float> GetTopColliders()
677 { 700 {
678 return new Dictionary<uint, float>(); 701 Dictionary<uint, float> topColliders;
702
703 lock (PhysObjects)
704 {
705 foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
706 {
707 kvp.Value.ComputeCollisionScore();
708 }
709
710 List<BSPhysObject> orderedPrims = new List<BSPhysObject>(PhysObjects.Values);
711 orderedPrims.OrderByDescending(p => p.CollisionScore);
712 topColliders = orderedPrims.Take(25).ToDictionary(p => p.LocalID, p => p.CollisionScore);
713 }
714
715 return topColliders;
679 } 716 }
680 717
681 public override bool IsThreaded { get { return false; } } 718 public override bool IsThreaded { get { return false; } }
682 719
683 #region Taints 720 #region Taints
721 // The simulation execution order is:
722 // Simulate()
723 // DoOneTimeTaints
724 // TriggerPreStepEvent
725 // DoOneTimeTaints
726 // Step()
727 // ProcessAndSendToSimulatorCollisions
728 // ProcessAndSendToSimulatorPropertyUpdates
729 // TriggerPostStepEvent
684 730
685 // Calls to the PhysicsActors can't directly call into the physics engine 731 // Calls to the PhysicsActors can't directly call into the physics engine
686 // because it might be busy. We delay changes to a known time. 732 // because it might be busy. We delay changes to a known time.
@@ -707,58 +753,35 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
707 TaintedObject(ident, callback); 753 TaintedObject(ident, callback);
708 } 754 }
709 755
756 private void TriggerPreStepEvent(float timeStep)
757 {
758 PreStepAction actions = BeforeStep;
759 if (actions != null)
760 actions(timeStep);
761
762 }
763
764 private void TriggerPostStepEvent(float timeStep)
765 {
766 PostStepAction actions = AfterStep;
767 if (actions != null)
768 actions(timeStep);
769
770 }
771
710 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues 772 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues
711 // a callback into itself to do the actual property change. That callback is called 773 // a callback into itself to do the actual property change. That callback is called
712 // here just before the physics engine is called to step the simulation. 774 // here just before the physics engine is called to step the simulation.
713 public void ProcessTaints() 775 public void ProcessTaints()
714 { 776 {
715 InTaintTime = true; // Only used for debugging so locking is not necessary.
716 ProcessRegularTaints(); 777 ProcessRegularTaints();
717 ProcessPostTaintTaints(); 778 ProcessPostTaintTaints();
718 InTaintTime = false;
719 } 779 }
720 780
721 private void ProcessRegularTaints() 781 private void ProcessRegularTaints()
722 { 782 {
723 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process 783 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process
724 { 784 {
725 /*
726 // Code to limit the number of taints processed per step. Meant to limit step time.
727 // Unsure if a good idea as code assumes that taints are done before the step.
728 int taintCount = m_taintsToProcessPerStep;
729 TaintCallbackEntry oneCallback = new TaintCallbackEntry();
730 while (_taintOperations.Count > 0 && taintCount-- > 0)
731 {
732 bool gotOne = false;
733 lock (_taintLock)
734 {
735 if (_taintOperations.Count > 0)
736 {
737 oneCallback = _taintOperations[0];
738 _taintOperations.RemoveAt(0);
739 gotOne = true;
740 }
741 }
742 if (gotOne)
743 {
744 try
745 {
746 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident);
747 oneCallback.callback();
748 }
749 catch (Exception e)
750 {
751 DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG
752 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e);
753 }
754 }
755 }
756 if (_taintOperations.Count > 0)
757 {
758 DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count);
759 }
760 */
761
762 // swizzle a new list into the list location so we can process what's there 785 // swizzle a new list into the list location so we can process what's there
763 List<TaintCallbackEntry> oldList; 786 List<TaintCallbackEntry> oldList;
764 lock (_taintLock) 787 lock (_taintLock)
@@ -797,6 +820,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
797 return; 820 return;
798 } 821 }
799 822
823 // Taints that happen after the normal taint processing but before the simulation step.
800 private void ProcessPostTaintTaints() 824 private void ProcessPostTaintTaints()
801 { 825 {
802 if (_postTaintOperations.Count > 0) 826 if (_postTaintOperations.Count > 0)
@@ -824,45 +848,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
824 } 848 }
825 } 849 }
826 850
827 public void PostStepTaintObject(String ident, TaintCallback callback)
828 {
829 if (!m_initialized) return;
830
831 lock (_taintLock)
832 {
833 _postStepOperations.Add(new TaintCallbackEntry(ident, callback));
834 }
835
836 return;
837 }
838
839 private void ProcessPostStepTaints()
840 {
841 if (_postStepOperations.Count > 0)
842 {
843 List<TaintCallbackEntry> oldList;
844 lock (_taintLock)
845 {
846 oldList = _postStepOperations;
847 _postStepOperations = new List<TaintCallbackEntry>();
848 }
849
850 foreach (TaintCallbackEntry tcbe in oldList)
851 {
852 try
853 {
854 DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
855 tcbe.callback();
856 }
857 catch (Exception e)
858 {
859 m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
860 }
861 }
862 oldList.Clear();
863 }
864 }
865
866 // Only used for debugging. Does not change state of anything so locking is not necessary. 851 // Only used for debugging. Does not change state of anything so locking is not necessary.
867 public bool AssertInTaintTime(string whereFrom) 852 public bool AssertInTaintTime(string whereFrom)
868 { 853 {
@@ -870,565 +855,93 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
870 { 855 {
871 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); 856 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
872 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); 857 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
873 Util.PrintCallStack(); // Prints the stack into the DEBUG log file. 858 // Util.PrintCallStack(DetailLog);
874 } 859 }
875 return InTaintTime; 860 return InTaintTime;
876 } 861 }
877 862
878 #endregion // Taints 863 #endregion // Taints
879 864
880 #region Vehicles 865 #region IPhysicsParameters
881 866 // Get the list of parameters this physics engine supports
882 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) 867 public PhysParameterEntry[] GetParameterList()
883 { 868 {
884 RemoveVehiclePrim(vehic); 869 BSParam.BuildParameterTable();
885 if (newType != Vehicle.TYPE_NONE) 870 return BSParam.SettableParameters;
886 {
887 // make it so the scene will call us each tick to do vehicle things
888 AddVehiclePrim(vehic);
889 }
890 } 871 }
891 872
892 // Make so the scene will call this prim for vehicle actions each tick. 873 // Set parameter on a specific or all instances.
893 // Safe to call if prim is already in the vehicle list. 874 // Return 'false' if not able to set the parameter.
894 public void AddVehiclePrim(BSPrim vehicle) 875 // Setting the value in the m_params block will change the value the physics engine
876 // will use the next time since it's pinned and shared memory.
877 // Some of the values require calling into the physics engine to get the new
878 // value activated ('terrainFriction' for instance).
879 public bool SetPhysicsParameter(string parm, string val, uint localID)
895 { 880 {
896 lock (m_vehicles) 881 bool ret = false;
882
883 float valf = 0f;
884 if (val.ToLower() == "true")
897 { 885 {
898 if (!m_vehicles.Contains(vehicle)) 886 valf = PhysParameterEntry.NUMERIC_TRUE;
899 {
900 m_vehicles.Add(vehicle);
901 }
902 } 887 }
903 } 888 else
904
905 // Remove a prim from our list of vehicles.
906 // Safe to call if the prim is not in the vehicle list.
907 public void RemoveVehiclePrim(BSPrim vehicle)
908 {
909 lock (m_vehicles)
910 { 889 {
911 if (m_vehicles.Contains(vehicle)) 890 if (val.ToLower() == "false")
912 { 891 {
913 m_vehicles.Remove(vehicle); 892 valf = PhysParameterEntry.NUMERIC_FALSE;
914 } 893 }
915 } 894 else
916 }
917
918 // Some prims have extra vehicle actions
919 // Called at taint time!
920 private void ProcessVehicles(float timeStep)
921 {
922 foreach (BSPhysObject pobj in m_vehicles)
923 {
924 pobj.StepVehicle(timeStep);
925 }
926 }
927 #endregion Vehicles
928
929 #region INI and command line parameter processing
930
931 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
932 delegate float ParamGet(BSScene scene);
933 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
934 delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
935
936 private struct ParameterDefn
937 {
938 public string name; // string name of the parameter
939 public string desc; // a short description of what the parameter means
940 public float defaultValue; // default value if not specified anywhere else
941 public ParamUser userParam; // get the value from the configuration file
942 public ParamGet getter; // return the current value stored for this parameter
943 public ParamSet setter; // set the current value for this parameter
944 public SetOnObject onObject; // set the value on an object in the physical domain
945 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
946 {
947 name = n;
948 desc = d;
949 defaultValue = v;
950 userParam = u;
951 getter = g;
952 setter = s;
953 onObject = null;
954 }
955 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
956 {
957 name = n;
958 desc = d;
959 defaultValue = v;
960 userParam = u;
961 getter = g;
962 setter = s;
963 onObject = o;
964 }
965 }
966
967 // List of all of the externally visible parameters.
968 // For each parameter, this table maps a text name to getter and setters.
969 // To add a new externally referencable/settable parameter, add the paramter storage
970 // location somewhere in the program and make an entry in this table with the
971 // getters and setters.
972 // It is easiest to find an existing definition and copy it.
973 // Parameter values are floats. Booleans are converted to a floating value.
974 //
975 // A ParameterDefn() takes the following parameters:
976 // -- the text name of the parameter. This is used for console input and ini file.
977 // -- a short text description of the parameter. This shows up in the console listing.
978 // -- a delegate for fetching the parameter from the ini file.
979 // Should handle fetching the right type from the ini file and converting it.
980 // -- a delegate for getting the value as a float
981 // -- a delegate for setting the value from a float
982 //
983 // The single letter parameters for the delegates are:
984 // s = BSScene
985 // o = BSPhysObject
986 // p = string parameter name
987 // l = localID of referenced object
988 // v = float value
989 // cf = parameter configuration class (for fetching values from ini file)
990 private ParameterDefn[] ParameterDefinitions =
991 {
992 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
993 ConfigurationParameters.numericTrue,
994 (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
995 (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); },
996 (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ),
997 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
998 ConfigurationParameters.numericFalse,
999 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
1000 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
1001 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
1002 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
1003 ConfigurationParameters.numericTrue,
1004 (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); },
1005 (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); },
1006 (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ),
1007
1008 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
1009 8f,
1010 (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); },
1011 (s) => { return s.MeshLOD; },
1012 (s,p,l,v) => { s.MeshLOD = v; } ),
1013 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
1014 16f,
1015 (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
1016 (s) => { return s.MeshMegaPrimLOD; },
1017 (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ),
1018 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
1019 10f,
1020 (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
1021 (s) => { return s.MeshMegaPrimThreshold; },
1022 (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ),
1023 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
1024 32f,
1025 (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); },
1026 (s) => { return s.SculptLOD; },
1027 (s,p,l,v) => { s.SculptLOD = v; } ),
1028
1029 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
1030 10f,
1031 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
1032 (s) => { return (float)s.m_maxSubSteps; },
1033 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
1034 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
1035 1f / 60f,
1036 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
1037 (s) => { return (float)s.m_fixedTimeStep; },
1038 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
1039 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
1040 2048f,
1041 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
1042 (s) => { return (float)s.m_maxCollisionsPerFrame; },
1043 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
1044 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
1045 8000f,
1046 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
1047 (s) => { return (float)s.m_maxUpdatesPerFrame; },
1048 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
1049 new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
1050 500f,
1051 (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
1052 (s) => { return (float)s.m_taintsToProcessPerStep; },
1053 (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
1054 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
1055 10000.01f,
1056 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
1057 (s) => { return (float)s.MaximumObjectMass; },
1058 (s,p,l,v) => { s.MaximumObjectMass = v; } ),
1059
1060 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
1061 2200f,
1062 (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); },
1063 (s) => { return (float)s.PID_D; },
1064 (s,p,l,v) => { s.PID_D = v; } ),
1065 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
1066 900f,
1067 (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); },
1068 (s) => { return (float)s.PID_P; },
1069 (s,p,l,v) => { s.PID_P = v; } ),
1070
1071 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
1072 0.5f,
1073 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); },
1074 (s) => { return s.m_params[0].defaultFriction; },
1075 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ),
1076 new ParameterDefn("DefaultDensity", "Density for new objects" ,
1077 10.000006836f, // Aluminum g/cm3
1078 (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); },
1079 (s) => { return s.m_params[0].defaultDensity; },
1080 (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ),
1081 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
1082 0f,
1083 (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); },
1084 (s) => { return s.m_params[0].defaultRestitution; },
1085 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ),
1086 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
1087 0f,
1088 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); },
1089 (s) => { return s.m_params[0].collisionMargin; },
1090 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ),
1091 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
1092 -9.80665f,
1093 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
1094 (s) => { return s.m_params[0].gravity; },
1095 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); },
1096 (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ),
1097
1098
1099 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
1100 0f,
1101 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
1102 (s) => { return s.m_params[0].linearDamping; },
1103 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); },
1104 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, s.m_params[0].angularDamping); } ),
1105 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
1106 0f,
1107 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
1108 (s) => { return s.m_params[0].angularDamping; },
1109 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); },
1110 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, s.m_params[0].linearDamping, v); } ),
1111 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
1112 0.2f,
1113 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
1114 (s) => { return s.m_params[0].deactivationTime; },
1115 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); },
1116 (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ),
1117 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
1118 0.8f,
1119 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
1120 (s) => { return s.m_params[0].linearSleepingThreshold; },
1121 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); },
1122 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
1123 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
1124 1.0f,
1125 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
1126 (s) => { return s.m_params[0].angularSleepingThreshold; },
1127 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); },
1128 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
1129 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
1130 0f, // set to zero to disable
1131 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
1132 (s) => { return s.m_params[0].ccdMotionThreshold; },
1133 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); },
1134 (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ),
1135 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
1136 0f,
1137 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
1138 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
1139 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); },
1140 (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ),
1141 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
1142 0.1f,
1143 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
1144 (s) => { return s.m_params[0].contactProcessingThreshold; },
1145 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); },
1146 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ),
1147
1148 new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
1149 (float)BSTerrainPhys.TerrainImplementation.Mesh,
1150 (s,cf,p,v) => { s.m_params[0].terrainImplementation = cf.GetFloat(p,v); },
1151 (s) => { return s.m_params[0].terrainImplementation; },
1152 (s,p,l,v) => { s.m_params[0].terrainImplementation = v; } ),
1153 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1154 0.5f,
1155 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
1156 (s) => { return s.m_params[0].terrainFriction; },
1157 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ),
1158 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
1159 0.8f,
1160 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
1161 (s) => { return s.m_params[0].terrainHitFraction; },
1162 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ),
1163 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
1164 0f,
1165 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
1166 (s) => { return s.m_params[0].terrainRestitution; },
1167 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ),
1168 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1169 0.2f,
1170 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1171 (s) => { return s.m_params[0].avatarFriction; },
1172 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1173 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
1174 10f,
1175 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); },
1176 (s) => { return s.m_params[0].avatarStandingFriction; },
1177 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ),
1178 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
1179 60f,
1180 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
1181 (s) => { return s.m_params[0].avatarDensity; },
1182 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
1183 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
1184 0f,
1185 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1186 (s) => { return s.m_params[0].avatarRestitution; },
1187 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1188 new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
1189 0.6f,
1190 (s,cf,p,v) => { s.m_params[0].avatarCapsuleWidth = cf.GetFloat(p, v); },
1191 (s) => { return s.m_params[0].avatarCapsuleWidth; },
1192 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleWidth, p, l, v); } ),
1193 new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
1194 0.45f,
1195 (s,cf,p,v) => { s.m_params[0].avatarCapsuleDepth = cf.GetFloat(p, v); },
1196 (s) => { return s.m_params[0].avatarCapsuleDepth; },
1197 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleDepth, p, l, v); } ),
1198 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1199 1.5f,
1200 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
1201 (s) => { return s.m_params[0].avatarCapsuleHeight; },
1202 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
1203 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
1204 0.1f,
1205 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
1206 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1207 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1208
1209
1210 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1211 0f,
1212 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1213 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1214 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1215 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
1216 0f,
1217 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
1218 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
1219 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
1220 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1221 ConfigurationParameters.numericFalse,
1222 (s,cf,p,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1223 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1224 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1225 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
1226 ConfigurationParameters.numericFalse,
1227 (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1228 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1229 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1230 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1231 ConfigurationParameters.numericTrue,
1232 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1233 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1234 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1235 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1236 ConfigurationParameters.numericTrue,
1237 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1238 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1239 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
1240 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
1241 ConfigurationParameters.numericFalse,
1242 (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1243 (s) => { return s.m_params[0].shouldEnableFrictionCaching; },
1244 (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ),
1245 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
1246 0f, // zero says use Bullet default
1247 (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); },
1248 (s) => { return s.m_params[0].numberOfSolverIterations; },
1249 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1250
1251 new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
1252 (float)BSLinkset.LinksetImplementation.Compound,
1253 (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); },
1254 (s) => { return s.m_params[0].linksetImplementation; },
1255 (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ),
1256 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1257 ConfigurationParameters.numericFalse,
1258 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1259 (s) => { return s.m_params[0].linkConstraintUseFrameOffset; },
1260 (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ),
1261 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
1262 ConfigurationParameters.numericTrue,
1263 (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1264 (s) => { return s.m_params[0].linkConstraintEnableTransMotor; },
1265 (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ),
1266 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
1267 5.0f,
1268 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
1269 (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; },
1270 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ),
1271 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
1272 0.1f,
1273 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1274 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1275 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1276 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
1277 0.1f,
1278 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1279 (s) => { return s.m_params[0].linkConstraintCFM; },
1280 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
1281 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
1282 0.1f,
1283 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1284 (s) => { return s.m_params[0].linkConstraintERP; },
1285 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
1286 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
1287 40,
1288 (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); },
1289 (s) => { return s.m_params[0].linkConstraintSolverIterations; },
1290 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
1291
1292 new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)",
1293 0f,
1294 (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); },
1295 (s) => { return (float)s.m_params[0].physicsLoggingFrames; },
1296 (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ),
1297 };
1298
1299 // Convert a boolean to our numeric true and false values
1300 public float NumericBool(bool b)
1301 {
1302 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
1303 }
1304
1305 // Convert numeric true and false values to a boolean
1306 public bool BoolNumeric(float b)
1307 {
1308 return (b == ConfigurationParameters.numericTrue ? true : false);
1309 }
1310
1311 // Search through the parameter definitions and return the matching
1312 // ParameterDefn structure.
1313 // Case does not matter as names are compared after converting to lower case.
1314 // Returns 'false' if the parameter is not found.
1315 private bool TryGetParameter(string paramName, out ParameterDefn defn)
1316 {
1317 bool ret = false;
1318 ParameterDefn foundDefn = new ParameterDefn();
1319 string pName = paramName.ToLower();
1320
1321 foreach (ParameterDefn parm in ParameterDefinitions)
1322 {
1323 if (pName == parm.name.ToLower())
1324 { 895 {
1325 foundDefn = parm; 896 try
1326 ret = true; 897 {
1327 break; 898 valf = float.Parse(val);
899 }
900 catch
901 {
902 valf = 0f;
903 }
1328 } 904 }
1329 } 905 }
1330 defn = foundDefn;
1331 return ret;
1332 }
1333
1334 // Pass through the settable parameters and set the default values
1335 private void SetParameterDefaultValues()
1336 {
1337 foreach (ParameterDefn parm in ParameterDefinitions)
1338 {
1339 parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
1340 }
1341 }
1342 906
1343 // Get user set values out of the ini file. 907 BSParam.ParameterDefn theParam;
1344 private void SetParameterConfigurationValues(IConfig cfg) 908 if (BSParam.TryGetParameter(parm, out theParam))
1345 {
1346 foreach (ParameterDefn parm in ParameterDefinitions)
1347 { 909 {
1348 parm.userParam(this, cfg, parm.name, parm.defaultValue); 910 // Set the value in the C# code
1349 } 911 theParam.setter(this, parm, localID, valf);
1350 }
1351 912
1352 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; 913 // Optionally set the parameter in the unmanaged code
1353 914 if (theParam.onObject != null)
1354 // This creates an array in the correct format for returning the list of
1355 // parameters. This is used by the 'list' option of the 'physics' command.
1356 private void BuildParameterTable()
1357 {
1358 if (SettableParameters.Length < ParameterDefinitions.Length)
1359 {
1360 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1361 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1362 { 915 {
1363 ParameterDefn pd = ParameterDefinitions[ii]; 916 // update all the localIDs specified
1364 entries.Add(new PhysParameterEntry(pd.name, pd.desc)); 917 // If the local ID is APPLY_TO_NONE, just change the default value
918 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
919 // If the localID is a specific object, apply the parameter change to only that object
920 List<uint> objectIDs = new List<uint>();
921 switch (localID)
922 {
923 case PhysParameterEntry.APPLY_TO_NONE:
924 // This will cause a call into the physical world if some operation is specified (SetOnObject).
925 objectIDs.Add(TERRAIN_ID);
926 TaintedUpdateParameter(parm, objectIDs, valf);
927 break;
928 case PhysParameterEntry.APPLY_TO_ALL:
929 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
930 TaintedUpdateParameter(parm, objectIDs, valf);
931 break;
932 default:
933 // setting only one localID
934 objectIDs.Add(localID);
935 TaintedUpdateParameter(parm, objectIDs, valf);
936 break;
937 }
1365 } 938 }
1366 939
1367 // make the list in alphabetical order for estetic reasons
1368 entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
1369 {
1370 return ppe1.name.CompareTo(ppe2.name);
1371 });
1372
1373 SettableParameters = entries.ToArray();
1374 }
1375 }
1376
1377
1378 #region IPhysicsParameters
1379 // Get the list of parameters this physics engine supports
1380 public PhysParameterEntry[] GetParameterList()
1381 {
1382 BuildParameterTable();
1383 return SettableParameters;
1384 }
1385
1386 // Set parameter on a specific or all instances.
1387 // Return 'false' if not able to set the parameter.
1388 // Setting the value in the m_params block will change the value the physics engine
1389 // will use the next time since it's pinned and shared memory.
1390 // Some of the values require calling into the physics engine to get the new
1391 // value activated ('terrainFriction' for instance).
1392 public bool SetPhysicsParameter(string parm, float val, uint localID)
1393 {
1394 bool ret = false;
1395 ParameterDefn theParam;
1396 if (TryGetParameter(parm, out theParam))
1397 {
1398 theParam.setter(this, parm, localID, val);
1399 ret = true; 940 ret = true;
1400 } 941 }
1401 return ret; 942 return ret;
1402 } 943 }
1403 944
1404 // update all the localIDs specified
1405 // If the local ID is APPLY_TO_NONE, just change the default value
1406 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
1407 // If the localID is a specific object, apply the parameter change to only that object
1408 private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val)
1409 {
1410 List<uint> objectIDs = new List<uint>();
1411 switch (localID)
1412 {
1413 case PhysParameterEntry.APPLY_TO_NONE:
1414 defaultLoc = val; // setting only the default value
1415 // This will cause a call into the physical world if some operation is specified (SetOnObject).
1416 objectIDs.Add(TERRAIN_ID);
1417 TaintedUpdateParameter(parm, objectIDs, val);
1418 break;
1419 case PhysParameterEntry.APPLY_TO_ALL:
1420 defaultLoc = val; // setting ALL also sets the default value
1421 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
1422 TaintedUpdateParameter(parm, objectIDs, val);
1423 break;
1424 default:
1425 // setting only one localID
1426 objectIDs.Add(localID);
1427 TaintedUpdateParameter(parm, objectIDs, val);
1428 break;
1429 }
1430 }
1431
1432 // schedule the actual updating of the paramter to when the phys engine is not busy 945 // schedule the actual updating of the paramter to when the phys engine is not busy
1433 private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val) 946 private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val)
1434 { 947 {
@@ -1436,16 +949,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1436 List<uint> xlIDs = lIDs; 949 List<uint> xlIDs = lIDs;
1437 string xparm = parm; 950 string xparm = parm;
1438 TaintedObject("BSScene.UpdateParameterSet", delegate() { 951 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1439 ParameterDefn thisParam; 952 BSParam.ParameterDefn thisParam;
1440 if (TryGetParameter(xparm, out thisParam)) 953 if (BSParam.TryGetParameter(xparm, out thisParam))
1441 { 954 {
1442 if (thisParam.onObject != null) 955 if (thisParam.onObject != null)
1443 { 956 {
1444 foreach (uint lID in xlIDs) 957 foreach (uint lID in xlIDs)
1445 { 958 {
1446 BSPhysObject theObject = null; 959 BSPhysObject theObject = null;
1447 PhysObjects.TryGetValue(lID, out theObject); 960 if (PhysObjects.TryGetValue(lID, out theObject))
1448 thisParam.onObject(this, theObject, xval); 961 thisParam.onObject(this, theObject, xval);
1449 } 962 }
1450 } 963 }
1451 } 964 }
@@ -1454,14 +967,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1454 967
1455 // Get parameter. 968 // Get parameter.
1456 // Return 'false' if not able to get the parameter. 969 // Return 'false' if not able to get the parameter.
1457 public bool GetPhysicsParameter(string parm, out float value) 970 public bool GetPhysicsParameter(string parm, out string value)
1458 { 971 {
1459 float val = 0f; 972 string val = String.Empty;
1460 bool ret = false; 973 bool ret = false;
1461 ParameterDefn theParam; 974 BSParam.ParameterDefn theParam;
1462 if (TryGetParameter(parm, out theParam)) 975 if (BSParam.TryGetParameter(parm, out theParam))
1463 { 976 {
1464 val = theParam.getter(this); 977 val = theParam.getter(this).ToString();
1465 ret = true; 978 ret = true;
1466 } 979 }
1467 value = val; 980 value = val;
@@ -1470,24 +983,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1470 983
1471 #endregion IPhysicsParameters 984 #endregion IPhysicsParameters
1472 985
1473 #endregion Runtime settable parameters
1474
1475 // Debugging routine for dumping detailed physical information for vehicle prims
1476 private void DumpVehicles()
1477 {
1478 foreach (BSPrim prim in m_vehicles)
1479 {
1480 BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr);
1481 BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr);
1482 }
1483 }
1484
1485 // Invoke the detailed logger and output something if it's enabled. 986 // Invoke the detailed logger and output something if it's enabled.
1486 public void DetailLog(string msg, params Object[] args) 987 public void DetailLog(string msg, params Object[] args)
1487 { 988 {
1488 PhysicsLogging.Write(msg, args); 989 PhysicsLogging.Write(msg, args);
1489 // Add the Flush() if debugging crashes. Gets all the messages written out. 990 // Add the Flush() if debugging crashes. Gets all the messages written out.
1490 // PhysicsLogging.Flush(); 991 if (m_physicsLoggingDoFlush) PhysicsLogging.Flush();
1491 } 992 }
1492 // Used to fill in the LocalID when there isn't one. It's the correct number of characters. 993 // Used to fill in the LocalID when there isn't one. It's the correct number of characters.
1493 public const string DetailLogZero = "0000000000"; 994 public const string DetailLogZero = "0000000000";
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 892c34b..096b300 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -45,7 +45,7 @@ public sealed class BSShapeCollection : IDisposable
45 // Description of a Mesh 45 // Description of a Mesh
46 private struct MeshDesc 46 private struct MeshDesc
47 { 47 {
48 public IntPtr ptr; 48 public BulletShape shape;
49 public int referenceCount; 49 public int referenceCount;
50 public DateTime lastReferenced; 50 public DateTime lastReferenced;
51 public UInt64 shapeKey; 51 public UInt64 shapeKey;
@@ -55,7 +55,7 @@ public sealed class BSShapeCollection : IDisposable
55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. 55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
56 private struct HullDesc 56 private struct HullDesc
57 { 57 {
58 public IntPtr ptr; 58 public BulletShape shape;
59 public int referenceCount; 59 public int referenceCount;
60 public DateTime lastReferenced; 60 public DateTime lastReferenced;
61 public UInt64 shapeKey; 61 public UInt64 shapeKey;
@@ -65,9 +65,16 @@ public sealed class BSShapeCollection : IDisposable
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>(); 65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>(); 66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67 67
68 private bool DDetail = false;
69
68 public BSShapeCollection(BSScene physScene) 70 public BSShapeCollection(BSScene physScene)
69 { 71 {
70 PhysicsScene = physScene; 72 PhysicsScene = physScene;
73 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
74 // While detailed debugging is still active, this is better than commenting out all the
75 // DetailLog statements. When debugging slows down, this and the protected logging
76 // statements can be commented/removed.
77 DDetail = true;
71 } 78 }
72 79
73 public void Dispose() 80 public void Dispose()
@@ -91,7 +98,7 @@ public sealed class BSShapeCollection : IDisposable
91 // higher level dependencies on the shape or body. Mostly used for LinkSets to 98 // higher level dependencies on the shape or body. Mostly used for LinkSets to
92 // remove the physical constraints before the body is destroyed. 99 // remove the physical constraints before the body is destroyed.
93 // Called at taint-time!! 100 // Called at taint-time!!
94 public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, 101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim,
95 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) 102 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
96 { 103 {
97 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); 104 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
@@ -109,8 +116,7 @@ public sealed class BSShapeCollection : IDisposable
109 // rebuild the body around it. 116 // rebuild the body around it.
110 // Updates prim.BSBody with information/pointers to requested body 117 // Updates prim.BSBody with information/pointers to requested body
111 // Returns 'true' if BSBody was changed. 118 // Returns 'true' if BSBody was changed.
112 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, 119 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, bodyCallback);
113 prim.PhysShape, bodyCallback);
114 ret = newGeom || newBody; 120 ret = newGeom || newBody;
115 } 121 }
116 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", 122 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
@@ -119,51 +125,52 @@ public sealed class BSShapeCollection : IDisposable
119 return ret; 125 return ret;
120 } 126 }
121 127
128 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
129 {
130 return GetBodyAndShape(forceRebuild, sim, prim, null, null);
131 }
132
122 // Track another user of a body. 133 // Track another user of a body.
123 // We presume the caller has allocated the body. 134 // We presume the caller has allocated the body.
124 // Bodies only have one user so the body is just put into the world if not already there. 135 // Bodies only have one user so the body is just put into the world if not already there.
125 public void ReferenceBody(BulletBody body, bool inTaintTime) 136 private void ReferenceBody(BulletBody body)
126 { 137 {
127 lock (m_collectionActivityLock) 138 lock (m_collectionActivityLock)
128 { 139 {
129 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); 140 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
130 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() 141 if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
131 { 142 {
132 if (!BulletSimAPI.IsInWorld2(body.ptr)) 143 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body);
133 { 144 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
134 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); 145 }
135 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
136 }
137 });
138 } 146 }
139 } 147 }
140 148
141 // Release the usage of a body. 149 // Release the usage of a body.
142 // Called when releasing use of a BSBody. BSShape is handled separately. 150 // Called when releasing use of a BSBody. BSShape is handled separately.
143 public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) 151 // Called in taint time.
152 public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback )
144 { 153 {
145 if (body.ptr == IntPtr.Zero) 154 if (!body.HasPhysicalBody)
146 return; 155 return;
147 156
157 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
158
148 lock (m_collectionActivityLock) 159 lock (m_collectionActivityLock)
149 { 160 {
150 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() 161 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
151 { 162 // If the caller needs to know the old body is going away, pass the event up.
152 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", 163 if (bodyCallback != null) bodyCallback(body);
153 body.ID, body, inTaintTime);
154 // If the caller needs to know the old body is going away, pass the event up.
155 if (bodyCallback != null) bodyCallback(body);
156 164
157 if (BulletSimAPI.IsInWorld2(body.ptr)) 165 if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
158 { 166 {
159 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); 167 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
160 DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); 168 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
161 } 169 }
162 170
163 // Zero any reference to the shape so it is not freed when the body is deleted. 171 // Zero any reference to the shape so it is not freed when the body is deleted.
164 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); 172 PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
165 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); 173 PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
166 });
167 } 174 }
168 } 175 }
169 176
@@ -184,17 +191,17 @@ public sealed class BSShapeCollection : IDisposable
184 { 191 {
185 // There is an existing instance of this mesh. 192 // There is an existing instance of this mesh.
186 meshDesc.referenceCount++; 193 meshDesc.referenceCount++;
187 DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", 194 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
188 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 195 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
189 } 196 }
190 else 197 else
191 { 198 {
192 // This is a new reference to a mesh 199 // This is a new reference to a mesh
193 meshDesc.ptr = shape.ptr; 200 meshDesc.shape = shape.Clone();
194 meshDesc.shapeKey = shape.shapeKey; 201 meshDesc.shapeKey = shape.shapeKey;
195 // We keep a reference to the underlying IMesh data so a hull can be built 202 // We keep a reference to the underlying IMesh data so a hull can be built
196 meshDesc.referenceCount = 1; 203 meshDesc.referenceCount = 1;
197 DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", 204 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
198 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 205 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
199 ret = true; 206 ret = true;
200 } 207 }
@@ -207,16 +214,16 @@ public sealed class BSShapeCollection : IDisposable
207 { 214 {
208 // There is an existing instance of this hull. 215 // There is an existing instance of this hull.
209 hullDesc.referenceCount++; 216 hullDesc.referenceCount++;
210 DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", 217 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
211 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 218 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
212 } 219 }
213 else 220 else
214 { 221 {
215 // This is a new reference to a hull 222 // This is a new reference to a hull
216 hullDesc.ptr = shape.ptr; 223 hullDesc.shape = shape.Clone();
217 hullDesc.shapeKey = shape.shapeKey; 224 hullDesc.shapeKey = shape.shapeKey;
218 hullDesc.referenceCount = 1; 225 hullDesc.referenceCount = 1;
219 DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", 226 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
220 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 227 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
221 ret = true; 228 ret = true;
222 229
@@ -234,44 +241,43 @@ public sealed class BSShapeCollection : IDisposable
234 } 241 }
235 242
236 // Release the usage of a shape. 243 // Release the usage of a shape.
237 public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) 244 public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback)
238 { 245 {
239 if (shape.ptr == IntPtr.Zero) 246 if (!shape.HasPhysicalShape)
240 return; 247 return;
241 248
242 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() 249 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape");
250
251 if (shape.HasPhysicalShape)
243 { 252 {
244 if (shape.ptr != IntPtr.Zero) 253 if (shape.isNativeShape)
245 { 254 {
246 if (shape.isNativeShape) 255 // Native shapes are not tracked and are released immediately
247 { 256 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}",
248 // Native shapes are not tracked and are released immediately 257 BSScene.DetailLogZero, shape.AddrString);
249 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", 258 if (shapeCallback != null) shapeCallback(shape);
250 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); 259 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
251 if (shapeCallback != null) shapeCallback(shape); 260 }
252 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); 261 else
253 } 262 {
254 else 263 switch (shape.type)
255 { 264 {
256 switch (shape.type) 265 case BSPhysicsShapeType.SHAPE_HULL:
257 { 266 DereferenceHull(shape, shapeCallback);
258 case BSPhysicsShapeType.SHAPE_HULL: 267 break;
259 DereferenceHull(shape, shapeCallback); 268 case BSPhysicsShapeType.SHAPE_MESH:
260 break; 269 DereferenceMesh(shape, shapeCallback);
261 case BSPhysicsShapeType.SHAPE_MESH: 270 break;
262 DereferenceMesh(shape, shapeCallback); 271 case BSPhysicsShapeType.SHAPE_COMPOUND:
263 break; 272 DereferenceCompound(shape, shapeCallback);
264 case BSPhysicsShapeType.SHAPE_COMPOUND: 273 break;
265 DereferenceCompound(shape, shapeCallback); 274 case BSPhysicsShapeType.SHAPE_UNKNOWN:
266 break; 275 break;
267 case BSPhysicsShapeType.SHAPE_UNKNOWN: 276 default:
268 break; 277 break;
269 default:
270 break;
271 }
272 } 278 }
273 } 279 }
274 }); 280 }
275 } 281 }
276 282
277 // Count down the reference count for a mesh shape 283 // Count down the reference count for a mesh shape
@@ -286,7 +292,7 @@ public sealed class BSShapeCollection : IDisposable
286 if (shapeCallback != null) shapeCallback(shape); 292 if (shapeCallback != null) shapeCallback(shape);
287 meshDesc.lastReferenced = System.DateTime.Now; 293 meshDesc.lastReferenced = System.DateTime.Now;
288 Meshes[shape.shapeKey] = meshDesc; 294 Meshes[shape.shapeKey] = meshDesc;
289 DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", 295 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
290 BSScene.DetailLogZero, shape, meshDesc.referenceCount); 296 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
291 297
292 } 298 }
@@ -307,7 +313,7 @@ public sealed class BSShapeCollection : IDisposable
307 313
308 hullDesc.lastReferenced = System.DateTime.Now; 314 hullDesc.lastReferenced = System.DateTime.Now;
309 Hulls[shape.shapeKey] = hullDesc; 315 Hulls[shape.shapeKey] = hullDesc;
310 DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", 316 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
311 BSScene.DetailLogZero, shape, hullDesc.referenceCount); 317 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
312 } 318 }
313 } 319 }
@@ -320,57 +326,56 @@ public sealed class BSShapeCollection : IDisposable
320 // Called at taint-time. 326 // Called at taint-time.
321 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) 327 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
322 { 328 {
323 if (!BulletSimAPI.IsCompound2(shape.ptr)) 329 if (!PhysicsScene.PE.IsCompound(shape))
324 { 330 {
325 // Failed the sanity check!! 331 // Failed the sanity check!!
326 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", 332 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
327 LogHeader, shape.type, shape.ptr.ToString("X")); 333 LogHeader, shape.type, shape.AddrString);
328 DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", 334 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
329 BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); 335 BSScene.DetailLogZero, shape.type, shape.AddrString);
330 return; 336 return;
331 } 337 }
332 338
333 int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); 339 int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape);
334 DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); 340 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
335 341
336 for (int ii = numChildren - 1; ii >= 0; ii--) 342 for (int ii = numChildren - 1; ii >= 0; ii--)
337 { 343 {
338 IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); 344 BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii);
339 DereferenceAnonCollisionShape(childShape); 345 DereferenceAnonCollisionShape(childShape);
340 } 346 }
341 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); 347 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
342 } 348 }
343 349
344 // Sometimes we have a pointer to a collision shape but don't know what type it is. 350 // Sometimes we have a pointer to a collision shape but don't know what type it is.
345 // Figure out type and call the correct dereference routine. 351 // Figure out type and call the correct dereference routine.
346 // Called at taint-time. 352 // Called at taint-time.
347 private void DereferenceAnonCollisionShape(IntPtr cShape) 353 private void DereferenceAnonCollisionShape(BulletShape shapeInfo)
348 { 354 {
349 MeshDesc meshDesc; 355 MeshDesc meshDesc;
350 HullDesc hullDesc; 356 HullDesc hullDesc;
351 357
352 BulletShape shapeInfo = new BulletShape(cShape); 358 if (TryGetMeshByPtr(shapeInfo, out meshDesc))
353 if (TryGetMeshByPtr(cShape, out meshDesc))
354 { 359 {
355 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH; 360 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
356 shapeInfo.shapeKey = meshDesc.shapeKey; 361 shapeInfo.shapeKey = meshDesc.shapeKey;
357 } 362 }
358 else 363 else
359 { 364 {
360 if (TryGetHullByPtr(cShape, out hullDesc)) 365 if (TryGetHullByPtr(shapeInfo, out hullDesc))
361 { 366 {
362 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL; 367 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
363 shapeInfo.shapeKey = hullDesc.shapeKey; 368 shapeInfo.shapeKey = hullDesc.shapeKey;
364 } 369 }
365 else 370 else
366 { 371 {
367 if (BulletSimAPI.IsCompound2(cShape)) 372 if (PhysicsScene.PE.IsCompound(shapeInfo))
368 { 373 {
369 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND; 374 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
370 } 375 }
371 else 376 else
372 { 377 {
373 if (BulletSimAPI.IsNativeShape2(cShape)) 378 if (PhysicsScene.PE.IsNativeShape(shapeInfo))
374 { 379 {
375 shapeInfo.isNativeShape = true; 380 shapeInfo.isNativeShape = true;
376 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) 381 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
@@ -379,16 +384,16 @@ public sealed class BSShapeCollection : IDisposable
379 } 384 }
380 } 385 }
381 386
382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); 387 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
383 388
384 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) 389 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
385 { 390 {
386 DereferenceShape(shapeInfo, true, null); 391 DereferenceShape(shapeInfo, null);
387 } 392 }
388 else 393 else
389 { 394 {
390 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", 395 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}",
391 LogHeader, PhysicsScene.RegionName, cShape.ToString("X")); 396 LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString);
392 } 397 }
393 } 398 }
394 399
@@ -408,19 +413,18 @@ public sealed class BSShapeCollection : IDisposable
408 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) 413 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
409 { 414 {
410 // an avatar capsule is close to a native shape (it is not shared) 415 // an avatar capsule is close to a native shape (it is not shared)
411 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, 416 GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback);
412 FixedShapeKey.KEY_CAPSULE, shapeCallback); 417 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
414 ret = true; 418 ret = true;
415 haveShape = true; 419 haveShape = true;
416 } 420 }
417 421
418 // Compound shapes are handled special as they are rebuilt from scratch. 422 // Compound shapes are handled special as they are rebuilt from scratch.
419 // This isn't too great a hardship since most of the child shapes will already been created. 423 // This isn't too great a hardship since most of the child shapes will have already been created.
420 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) 424 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
421 { 425 {
422 ret = GetReferenceToCompoundShape(prim, shapeCallback); 426 ret = GetReferenceToCompoundShape(prim, shapeCallback);
423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); 427 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
424 haveShape = true; 428 haveShape = true;
425 } 429 }
426 430
@@ -432,8 +436,9 @@ public sealed class BSShapeCollection : IDisposable
432 return ret; 436 return ret;
433 } 437 }
434 438
435 // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. 439 // Create a mesh, hull or native shape.
436 private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) 440 // Return 'true' if the prim's shape was changed.
441 public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
437 { 442 {
438 bool ret = false; 443 bool ret = false;
439 bool haveShape = false; 444 bool haveShape = false;
@@ -443,8 +448,9 @@ public sealed class BSShapeCollection : IDisposable
443 // If the prim attributes are simple, this could be a simple Bullet native shape 448 // If the prim attributes are simple, this could be a simple Bullet native shape
444 if (!haveShape 449 if (!haveShape
445 && pbs != null 450 && pbs != null
451 && !pbs.SculptEntry
446 && nativeShapePossible 452 && nativeShapePossible
447 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) 453 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim)
448 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 454 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
449 && pbs.ProfileHollow == 0 455 && pbs.ProfileHollow == 0
450 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 456 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
@@ -453,35 +459,43 @@ public sealed class BSShapeCollection : IDisposable
453 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 459 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
454 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) 460 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
455 { 461 {
456 // It doesn't look like Bullet scales spheres so make sure the scales are all equal 462 // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
463 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
464 if (prim.PhysShape.HasPhysicalShape)
465 scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape);
466
467 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
468 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type);
469
470 // It doesn't look like Bullet scales native spheres so make sure the scales are all equal
457 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) 471 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
458 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) 472 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
459 { 473 {
460 haveShape = true; 474 haveShape = true;
461 if (forceRebuild 475 if (forceRebuild
462 || prim.Scale != prim.Size 476 || prim.Scale != scaleOfExistingShape
463 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE 477 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
464 ) 478 )
465 { 479 {
466 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, 480 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
467 FixedShapeKey.KEY_SPHERE, shapeCallback); 481 FixedShapeKey.KEY_SPHERE, shapeCallback);
468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
469 prim.LocalID, forceRebuild, prim.PhysShape);
470 } 482 }
483 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}",
484 prim.LocalID, forceRebuild, ret, prim.PhysShape);
471 } 485 }
472 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 486 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
473 { 487 {
474 haveShape = true; 488 haveShape = true;
475 if (forceRebuild 489 if (forceRebuild
476 || prim.Scale != prim.Size 490 || prim.Scale != scaleOfExistingShape
477 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX 491 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
478 ) 492 )
479 { 493 {
480 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, 494 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
481 FixedShapeKey.KEY_BOX, shapeCallback); 495 FixedShapeKey.KEY_BOX, shapeCallback);
482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
483 prim.LocalID, forceRebuild, prim.PhysShape);
484 } 496 }
497 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}",
498 prim.LocalID, forceRebuild, ret, prim.PhysShape);
485 } 499 }
486 } 500 }
487 501
@@ -494,23 +508,24 @@ public sealed class BSShapeCollection : IDisposable
494 return ret; 508 return ret;
495 } 509 }
496 510
511 // return 'true' if the prim's shape was changed.
497 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 512 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
498 { 513 {
499 514
500 bool ret = false; 515 bool ret = false;
501 // Note that if it's a native shape, the check for physical/non-physical is not 516 // Note that if it's a native shape, the check for physical/non-physical is not
502 // made. Native shapes work in either case. 517 // made. Native shapes work in either case.
503 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) 518 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
504 { 519 {
505 // Update prim.BSShape to reference a hull of this shape. 520 // Update prim.BSShape to reference a hull of this shape.
506 ret = GetReferenceToHull(prim,shapeCallback); 521 ret = GetReferenceToHull(prim,shapeCallback);
507 DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", 522 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
508 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); 523 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
509 } 524 }
510 else 525 else
511 { 526 {
512 ret = GetReferenceToMesh(prim, shapeCallback); 527 ret = GetReferenceToMesh(prim, shapeCallback);
513 DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", 528 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
514 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); 529 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
515 } 530 }
516 return ret; 531 return ret;
@@ -523,14 +538,15 @@ public sealed class BSShapeCollection : IDisposable
523 ShapeDestructionCallback shapeCallback) 538 ShapeDestructionCallback shapeCallback)
524 { 539 {
525 // release any previous shape 540 // release any previous shape
526 DereferenceShape(prim.PhysShape, true, shapeCallback); 541 DereferenceShape(prim.PhysShape, shapeCallback);
527 542
528 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); 543 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
529 544
530 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. 545 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
531 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", 546 if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
532 prim.LocalID, newShape, prim.Scale); 547 prim.LocalID, newShape, prim.Scale);
533 548
549 // native shapes are scaled by Bullet
534 prim.PhysShape = newShape; 550 prim.PhysShape = newShape;
535 return true; 551 return true;
536 } 552 }
@@ -550,20 +566,17 @@ public sealed class BSShapeCollection : IDisposable
550 566
551 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) 567 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
552 { 568 {
553 // The proper scale has been calculated in the prim. 569
554 newShape = new BulletShape( 570 newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale);
555 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) 571 if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
556 , shapeType);
557 DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
558 } 572 }
559 else 573 else
560 { 574 {
561 // Native shapes are scaled in Bullet so set the scaling to the size 575 // Native shapes are scaled in Bullet so set the scaling to the size
562 prim.Scale = prim.Size; 576 newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData);
563 nativeShapeData.Scale = prim.Scale; 577
564 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType);
565 } 578 }
566 if (newShape.ptr == IntPtr.Zero) 579 if (!newShape.HasPhysicalShape)
567 { 580 {
568 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 581 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
569 LogHeader, prim.LocalID, shapeType); 582 LogHeader, prim.LocalID, shapeType);
@@ -580,7 +593,7 @@ public sealed class BSShapeCollection : IDisposable
580 // Called at taint-time! 593 // Called at taint-time!
581 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 594 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
582 { 595 {
583 BulletShape newShape = new BulletShape(IntPtr.Zero); 596 BulletShape newShape = new BulletShape();
584 597
585 float lod; 598 float lod;
586 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 599 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
@@ -589,62 +602,96 @@ public sealed class BSShapeCollection : IDisposable
589 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) 602 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
590 return false; 603 return false;
591 604
592 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", 605 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2},size={3},lod={4}",
593 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); 606 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
594 607
595 // Since we're recreating new, get rid of the reference to the previous shape 608 // Since we're recreating new, get rid of the reference to the previous shape
596 DereferenceShape(prim.PhysShape, true, shapeCallback); 609 DereferenceShape(prim.PhysShape, shapeCallback);
597 610
598 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); 611 newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod);
599 // Take evasive action if the mesh was not constructed. 612 // Take evasive action if the mesh was not constructed.
600 newShape = VerifyMeshCreated(newShape, prim); 613 newShape = VerifyMeshCreated(newShape, prim);
601 614
602 ReferenceShape(newShape); 615 ReferenceShape(newShape);
603 616
604 // meshes are already scaled by the meshmerizer
605 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
606 prim.PhysShape = newShape; 617 prim.PhysShape = newShape;
607 618
608 return true; // 'true' means a new shape has been added to this prim 619 return true; // 'true' means a new shape has been added to this prim
609 } 620 }
610 621
611 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 622 private BulletShape CreatePhysicalMesh(BSPhysObject prim, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
612 { 623 {
613 IMesh meshData = null; 624 BulletShape newShape = new BulletShape();
614 IntPtr meshPtr = IntPtr.Zero; 625
615 MeshDesc meshDesc; 626 MeshDesc meshDesc;
616 if (Meshes.TryGetValue(newMeshKey, out meshDesc)) 627 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
617 { 628 {
618 // If the mesh has already been built just use it. 629 // If the mesh has already been built just use it.
619 meshPtr = meshDesc.ptr; 630 newShape = meshDesc.shape.Clone();
620 } 631 }
621 else 632 else
622 { 633 {
623 // Pass false for physicalness as this creates some sort of bounding box which we don't need 634 IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
624 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); 635 true,
636 false, // say it is not physical so a bounding box is not built
637 false, // do not cache the mesh and do not use previously built versions
638 false // It's NOT for ODE
639 );
625 640
626 if (meshData != null) 641 if (meshData != null)
627 { 642 {
643
628 int[] indices = meshData.getIndexListAsInt(); 644 int[] indices = meshData.getIndexListAsInt();
629 List<OMV.Vector3> vertices = meshData.getVertexList(); 645 int realIndicesIndex = indices.Length;
646 float[] verticesAsFloats = meshData.getVertexListAsFloat();
630 647
631 float[] verticesAsFloats = new float[vertices.Count * 3]; 648 if (BSParam.ShouldRemoveZeroWidthTriangles)
632 int vi = 0;
633 foreach (OMV.Vector3 vv in vertices)
634 { 649 {
635 verticesAsFloats[vi++] = vv.X; 650 // Remove degenerate triangles. These are triangles with two of the vertices
636 verticesAsFloats[vi++] = vv.Y; 651 // are the same. This is complicated by the problem that vertices are not
637 verticesAsFloats[vi++] = vv.Z; 652 // made unique in sculpties so we have to compare the values in the vertex.
653 realIndicesIndex = 0;
654 for (int tri = 0; tri < indices.Length; tri += 3)
655 {
656 // Compute displacements into vertex array for each vertex of the triangle
657 int v1 = indices[tri + 0] * 3;
658 int v2 = indices[tri + 1] * 3;
659 int v3 = indices[tri + 2] * 3;
660 // Check to see if any two of the vertices are the same
661 if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
662 && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
663 && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
664 || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
665 && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
666 && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
667 || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
668 && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
669 && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
670 )
671 {
672 // None of the vertices of the triangles are the same. This is a good triangle;
673 indices[realIndicesIndex + 0] = indices[tri + 0];
674 indices[realIndicesIndex + 1] = indices[tri + 1];
675 indices[realIndicesIndex + 2] = indices[tri + 2];
676 realIndicesIndex += 3;
677 }
678 }
638 } 679 }
680 DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
681 BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
639 682
640 // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", 683 if (realIndicesIndex != 0)
641 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); 684 {
642 685 newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World,
643 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, 686 realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
644 indices.GetLength(0), indices, vertices.Count, verticesAsFloats); 687 }
688 else
689 {
690 PhysicsScene.Logger.ErrorFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
691 LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name);
692 }
645 } 693 }
646 } 694 }
647 BulletShape newShape = new BulletShape(meshPtr, BSPhysicsShapeType.SHAPE_MESH);
648 newShape.shapeKey = newMeshKey; 695 newShape.shapeKey = newMeshKey;
649 696
650 return newShape; 697 return newShape;
@@ -663,19 +710,17 @@ public sealed class BSShapeCollection : IDisposable
663 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) 710 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
664 return false; 711 return false;
665 712
666 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", 713 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
667 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); 714 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
668 715
669 // Remove usage of the previous shape. 716 // Remove usage of the previous shape.
670 DereferenceShape(prim.PhysShape, true, shapeCallback); 717 DereferenceShape(prim.PhysShape, shapeCallback);
671 718
672 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); 719 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
673 newShape = VerifyMeshCreated(newShape, prim); 720 newShape = VerifyMeshCreated(newShape, prim);
674 721
675 ReferenceShape(newShape); 722 ReferenceShape(newShape);
676 723
677 // hulls are already scaled by the meshmerizer
678 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
679 prim.PhysShape = newShape; 724 prim.PhysShape = newShape;
680 return true; // 'true' means a new shape has been added to this prim 725 return true; // 'true' means a new shape has been added to this prim
681 } 726 }
@@ -684,18 +729,20 @@ public sealed class BSShapeCollection : IDisposable
684 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 729 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
685 { 730 {
686 731
732 BulletShape newShape = new BulletShape();
687 IntPtr hullPtr = IntPtr.Zero; 733 IntPtr hullPtr = IntPtr.Zero;
734
688 HullDesc hullDesc; 735 HullDesc hullDesc;
689 if (Hulls.TryGetValue(newHullKey, out hullDesc)) 736 if (Hulls.TryGetValue(newHullKey, out hullDesc))
690 { 737 {
691 // If the hull shape already is created, just use it. 738 // If the hull shape already is created, just use it.
692 hullPtr = hullDesc.ptr; 739 newShape = hullDesc.shape.Clone();
693 } 740 }
694 else 741 else
695 { 742 {
696 // Build a new hull in the physical world 743 // Build a new hull in the physical world
697 // Pass false for physicalness as this creates some sort of bounding box which we don't need 744 // Pass true for physicalness as this creates some sort of bounding box which we don't need
698 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); 745 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
699 if (meshData != null) 746 if (meshData != null)
700 { 747 {
701 748
@@ -777,14 +824,13 @@ public sealed class BSShapeCollection : IDisposable
777 } 824 }
778 } 825 }
779 // create the hull data structure in Bullet 826 // create the hull data structure in Bullet
780 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); 827 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
781 } 828 }
782 } 829 }
783 830
784 BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL);
785 newShape.shapeKey = newHullKey; 831 newShape.shapeKey = newHullKey;
786 832
787 return newShape; // 'true' means a new shape has been added to this prim 833 return newShape;
788 } 834 }
789 835
790 // Callback from convex hull creater with a newly created hull. 836 // Callback from convex hull creater with a newly created hull.
@@ -803,13 +849,12 @@ public sealed class BSShapeCollection : IDisposable
803 // Don't need to do this as the shape is freed when the new root shape is created below. 849 // Don't need to do this as the shape is freed when the new root shape is created below.
804 // DereferenceShape(prim.PhysShape, true, shapeCallback); 850 // DereferenceShape(prim.PhysShape, true, shapeCallback);
805 851
806 BulletShape cShape = new BulletShape( 852 BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false);
807 BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), BSPhysicsShapeType.SHAPE_COMPOUND);
808 853
809 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. 854 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
810 CreateGeomMeshOrHull(prim, shapeCallback); 855 CreateGeomMeshOrHull(prim, shapeCallback);
811 BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); 856 PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity);
812 DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", 857 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
813 prim.LocalID, cShape, prim.PhysShape); 858 prim.LocalID, cShape, prim.PhysShape);
814 859
815 prim.PhysShape = cShape; 860 prim.PhysShape = cShape;
@@ -822,14 +867,19 @@ public sealed class BSShapeCollection : IDisposable
822 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) 867 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
823 { 868 {
824 // level of detail based on size and type of the object 869 // level of detail based on size and type of the object
825 float lod = PhysicsScene.MeshLOD; 870 float lod = BSParam.MeshLOD;
871
872 // prims with curvy internal cuts need higher lod
873 if (pbs.HollowShape == HollowShape.Circle)
874 lod = BSParam.MeshCircularLOD;
875
826 if (pbs.SculptEntry) 876 if (pbs.SculptEntry)
827 lod = PhysicsScene.SculptLOD; 877 lod = BSParam.SculptLOD;
828 878
829 // Mega prims usually get more detail because one can interact with shape approximations at this size. 879 // Mega prims usually get more detail because one can interact with shape approximations at this size.
830 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); 880 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
831 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) 881 if (maxAxis > BSParam.MeshMegaPrimThreshold)
832 lod = PhysicsScene.MeshMegaPrimLOD; 882 lod = BSParam.MeshMegaPrimLOD;
833 883
834 retLod = lod; 884 retLod = lod;
835 return pbs.GetMeshKey(size, lod); 885 return pbs.GetMeshKey(size, lod);
@@ -851,16 +901,17 @@ public sealed class BSShapeCollection : IDisposable
851 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) 901 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
852 { 902 {
853 // If the shape was successfully created, nothing more to do 903 // If the shape was successfully created, nothing more to do
854 if (newShape.ptr != IntPtr.Zero) 904 if (newShape.HasPhysicalShape)
855 return newShape; 905 return newShape;
856 906
857 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset 907 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
858 if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) 908 if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero)
859 { 909 {
910 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lastFailed={1}", prim.LocalID, prim.LastAssetBuildFailed);
911 // This will prevent looping through this code as we keep trying to get the failed shape
860 prim.LastAssetBuildFailed = true; 912 prim.LastAssetBuildFailed = true;
913
861 BSPhysObject xprim = prim; 914 BSPhysObject xprim = prim;
862 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}",
863 LogHeader, prim.LocalID, prim.LastAssetBuildFailed);
864 Util.FireAndForget(delegate 915 Util.FireAndForget(delegate
865 { 916 {
866 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; 917 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
@@ -869,19 +920,34 @@ public sealed class BSShapeCollection : IDisposable
869 BSPhysObject yprim = xprim; // probably not necessary, but, just in case. 920 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
870 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) 921 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
871 { 922 {
872 if (!yprim.BaseShape.SculptEntry) 923 bool assetFound = false; // DEBUG DEBUG
873 return; 924 string mismatchIDs = String.Empty; // DEBUG DEBUG
874 if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) 925 if (asset != null && yprim.BaseShape.SculptEntry)
875 return; 926 {
876 927 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
877 yprim.BaseShape.SculptData = asset.Data; 928 {
878 // This will cause the prim to see that the filler shape is not the right 929 yprim.BaseShape.SculptData = asset.Data;
879 // one and try again to build the object. 930 // This will cause the prim to see that the filler shape is not the right
880 // No race condition with the normal shape setting since the rebuild is at taint time. 931 // one and try again to build the object.
881 yprim.ForceBodyShapeRebuild(false); 932 // No race condition with the normal shape setting since the rebuild is at taint time.
933 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
934 assetFound = true;
935 }
936 else
937 {
938 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
939 }
940 }
941 DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
942 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
882 943
883 }); 944 });
884 } 945 }
946 else
947 {
948 PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
949 LogHeader, PhysicsScene.Name);
950 }
885 }); 951 });
886 } 952 }
887 else 953 else
@@ -893,9 +959,9 @@ public sealed class BSShapeCollection : IDisposable
893 } 959 }
894 } 960 }
895 961
896 // While we figure out the real problem, stick a simple native shape on the object. 962 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
897 BulletShape fillinShape = 963 BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
898 BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); 964 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
899 965
900 return fillinShape; 966 return fillinShape;
901 } 967 }
@@ -904,49 +970,45 @@ public sealed class BSShapeCollection : IDisposable
904 // Updates prim.BSBody with the information about the new body if one is created. 970 // Updates prim.BSBody with the information about the new body if one is created.
905 // Returns 'true' if an object was actually created. 971 // Returns 'true' if an object was actually created.
906 // Called at taint-time. 972 // Called at taint-time.
907 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, 973 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BodyDestructionCallback bodyCallback)
908 BodyDestructionCallback bodyCallback)
909 { 974 {
910 bool ret = false; 975 bool ret = false;
911 976
912 // the mesh, hull or native shape must have already been created in Bullet 977 // the mesh, hull or native shape must have already been created in Bullet
913 bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero); 978 bool mustRebuild = !prim.PhysBody.HasPhysicalBody;
914 979
915 // If there is an existing body, verify it's of an acceptable type. 980 // If there is an existing body, verify it's of an acceptable type.
916 // If not a solid object, body is a GhostObject. Otherwise a RigidBody. 981 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
917 if (!mustRebuild) 982 if (!mustRebuild)
918 { 983 {
919 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr); 984 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody);
920 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY 985 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
921 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) 986 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
922 { 987 {
923 // If the collisionObject is not the correct type for solidness, rebuild what's there 988 // If the collisionObject is not the correct type for solidness, rebuild what's there
924 mustRebuild = true; 989 mustRebuild = true;
990 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,forceRebuildBecauseChangingBodyType,bodyType={1}", prim.LocalID, bodyType);
925 } 991 }
926 } 992 }
927 993
928 if (mustRebuild || forceRebuild) 994 if (mustRebuild || forceRebuild)
929 { 995 {
930 // Free any old body 996 // Free any old body
931 DereferenceBody(prim.PhysBody, true, bodyCallback); 997 DereferenceBody(prim.PhysBody, bodyCallback);
932 998
933 BulletBody aBody; 999 BulletBody aBody;
934 IntPtr bodyPtr = IntPtr.Zero;
935 if (prim.IsSolid) 1000 if (prim.IsSolid)
936 { 1001 {
937 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, 1002 aBody = PhysicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation);
938 prim.LocalID, prim.RawPosition, prim.RawOrientation); 1003 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody);
939 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
940 } 1004 }
941 else 1005 else
942 { 1006 {
943 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, 1007 aBody = PhysicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation);
944 prim.LocalID, prim.RawPosition, prim.RawOrientation); 1008 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
945 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
946 } 1009 }
947 aBody = new BulletBody(prim.LocalID, bodyPtr);
948 1010
949 ReferenceBody(aBody, true); 1011 ReferenceBody(aBody);
950 1012
951 prim.PhysBody = aBody; 1013 prim.PhysBody = aBody;
952 1014
@@ -956,13 +1018,13 @@ public sealed class BSShapeCollection : IDisposable
956 return ret; 1018 return ret;
957 } 1019 }
958 1020
959 private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc) 1021 private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc)
960 { 1022 {
961 bool ret = false; 1023 bool ret = false;
962 MeshDesc foundDesc = new MeshDesc(); 1024 MeshDesc foundDesc = new MeshDesc();
963 foreach (MeshDesc md in Meshes.Values) 1025 foreach (MeshDesc md in Meshes.Values)
964 { 1026 {
965 if (md.ptr == addr) 1027 if (md.shape.ReferenceSame(shape))
966 { 1028 {
967 foundDesc = md; 1029 foundDesc = md;
968 ret = true; 1030 ret = true;
@@ -974,13 +1036,13 @@ public sealed class BSShapeCollection : IDisposable
974 return ret; 1036 return ret;
975 } 1037 }
976 1038
977 private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc) 1039 private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc)
978 { 1040 {
979 bool ret = false; 1041 bool ret = false;
980 HullDesc foundDesc = new HullDesc(); 1042 HullDesc foundDesc = new HullDesc();
981 foreach (HullDesc hd in Hulls.Values) 1043 foreach (HullDesc hd in Hulls.Values)
982 { 1044 {
983 if (hd.ptr == addr) 1045 if (hd.shape.ReferenceSame(shape))
984 { 1046 {
985 foundDesc = hd; 1047 foundDesc = hd;
986 ret = true; 1048 ret = true;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index 96cd55e..ee18379 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -27,24 +27,19 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
31using System.Text; 30using System.Text;
32 31
32using OMV = OpenMetaverse;
33
33namespace OpenSim.Region.Physics.BulletSPlugin 34namespace OpenSim.Region.Physics.BulletSPlugin
34{ 35{
35public abstract class BSShape 36public abstract class BSShape
36{ 37{
37 public IntPtr ptr { get; set; }
38 public BSPhysicsShapeType type { get; set; }
39 public System.UInt64 key { get; set; }
40 public int referenceCount { get; set; } 38 public int referenceCount { get; set; }
41 public DateTime lastReferenced { get; set; } 39 public DateTime lastReferenced { get; set; }
42 40
43 public BSShape() 41 public BSShape()
44 { 42 {
45 ptr = IntPtr.Zero;
46 type = BSPhysicsShapeType.SHAPE_UNKNOWN;
47 key = 0;
48 referenceCount = 0; 43 referenceCount = 0;
49 lastReferenced = DateTime.Now; 44 lastReferenced = DateTime.Now;
50 } 45 }
@@ -63,7 +58,7 @@ public abstract class BSShape
63 } 58 }
64 59
65 // Compound shapes are handled special as they are rebuilt from scratch. 60 // Compound shapes are handled special as they are rebuilt from scratch.
66 // This isn't too great a hardship since most of the child shapes will already been created. 61 // This isn't too great a hardship since most of the child shapes will have already been created.
67 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) 62 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
68 { 63 {
69 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added 64 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
@@ -71,6 +66,14 @@ public abstract class BSShape
71 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); 66 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
72 } 67 }
73 68
69 // Avatars have their own unique shape
70 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_AVATAR)
71 {
72 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
73 ret = BSShapeAvatar.GetReference(prim);
74 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,avatarShape,shape={1}", prim.LocalID, ret);
75 }
76
74 if (ret == null) 77 if (ret == null)
75 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); 78 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
76 79
@@ -91,15 +94,17 @@ public abstract class BSShape
91 // All shapes have a static call to get a reference to the physical shape 94 // All shapes have a static call to get a reference to the physical shape
92 // protected abstract static BSShape GetReference(); 95 // protected abstract static BSShape GetReference();
93 96
97 // Returns a string for debugging that uniquily identifies the memory used by this instance
98 public virtual string AddrString
99 {
100 get { return "unknown"; }
101 }
102
94 public override string ToString() 103 public override string ToString()
95 { 104 {
96 StringBuilder buff = new StringBuilder(); 105 StringBuilder buff = new StringBuilder();
97 buff.Append("<p="); 106 buff.Append("<p=");
98 buff.Append(ptr.ToString("X")); 107 buff.Append(AddrString);
99 buff.Append(",s=");
100 buff.Append(type.ToString());
101 buff.Append(",k=");
102 buff.Append(key.ToString("X"));
103 buff.Append(",c="); 108 buff.Append(",c=");
104 buff.Append(referenceCount.ToString()); 109 buff.Append(referenceCount.ToString());
105 buff.Append(">"); 110 buff.Append(">");
@@ -126,7 +131,8 @@ public class BSShapeNative : BSShape
126 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) 131 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
127 { 132 {
128 // Native shapes are not shared and are always built anew. 133 // Native shapes are not shared and are always built anew.
129 return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); 134 //return new BSShapeNative(physicsScene, prim, shapeType, shapeKey);
135 return null;
130 } 136 }
131 137
132 private BSShapeNative(BSScene physicsScene, BSPhysObject prim, 138 private BSShapeNative(BSScene physicsScene, BSPhysObject prim,
@@ -141,14 +147,15 @@ public class BSShapeNative : BSShape
141 nativeShapeData.HullKey = (ulong)shapeKey; 147 nativeShapeData.HullKey = (ulong)shapeKey;
142 148
143 149
150 /*
144 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) 151 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
145 { 152 {
146 ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); 153 ptr = PhysicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale);
147 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 154 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
148 } 155 }
149 else 156 else
150 { 157 {
151 ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData); 158 ptr = PhysicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData);
152 } 159 }
153 if (ptr == IntPtr.Zero) 160 if (ptr == IntPtr.Zero)
154 { 161 {
@@ -157,15 +164,18 @@ public class BSShapeNative : BSShape
157 } 164 }
158 type = shapeType; 165 type = shapeType;
159 key = (UInt64)shapeKey; 166 key = (UInt64)shapeKey;
167 */
160 } 168 }
161 // Make this reference to the physical shape go away since native shapes are not shared. 169 // Make this reference to the physical shape go away since native shapes are not shared.
162 public override void Dereference(BSScene physicsScene) 170 public override void Dereference(BSScene physicsScene)
163 { 171 {
172 /*
164 // Native shapes are not tracked and are released immediately 173 // Native shapes are not tracked and are released immediately
165 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); 174 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
166 BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr); 175 PhysicsScene.PE.DeleteCollisionShape(physicsScene.World, this);
167 ptr = IntPtr.Zero; 176 ptr = IntPtr.Zero;
168 // Garbage collection will free up this instance. 177 // Garbage collection will free up this instance.
178 */
169 } 179 }
170} 180}
171 181
@@ -205,4 +215,143 @@ public class BSShapeCompound : BSShape
205 } 215 }
206 public override void Dereference(BSScene physicsScene) { } 216 public override void Dereference(BSScene physicsScene) { }
207} 217}
218
219public class BSShapeAvatar : BSShape
220{
221 private static string LogHeader = "[BULLETSIM SHAPE AVATAR]";
222 public BSShapeAvatar() : base()
223 {
224 }
225 public static BSShape GetReference(BSPhysObject prim)
226 {
227 return new BSShapeNull();
228 }
229 public override void Dereference(BSScene physicsScene) { }
230
231 // From the front:
232 // A---A
233 // / \
234 // B-------B
235 // / \ +Z
236 // C-----------C |
237 // \ / -Y --+-- +Y
238 // \ / |
239 // \ / -Z
240 // D-----D
241 // \ /
242 // E-E
243
244 // From the top A and E are just lines.
245 // B, C and D are hexagons:
246 //
247 // C1--C2 +X
248 // / \ |
249 // C0 C3 -Y --+-- +Y
250 // \ / |
251 // C5--C4 -X
252
253 // Zero goes directly through the middle so the offsets are from that middle axis
254 // and up and down from a middle horizon (A and E are the same distance from the zero).
255 // The height, width and depth is one. All scaling is done by the simulator.
256
257 // Z component -- how far the level is from the middle zero
258 private const float Aup = 0.5f;
259 private const float Bup = 0.4f;
260 private const float Cup = 0.3f;
261 private const float Dup = -0.4f;
262 private const float Eup = -0.5f;
263
264 // Y component -- distance from center to x0 and x3
265 private const float Awid = 0.25f;
266 private const float Bwid = 0.3f;
267 private const float Cwid = 0.5f;
268 private const float Dwid = 0.3f;
269 private const float Ewid = 0.2f;
270
271 // Y component -- distance from center to x1, x2, x4 and x5
272 private const float Afwid = 0.0f;
273 private const float Bfwid = 0.2f;
274 private const float Cfwid = 0.4f;
275 private const float Dfwid = 0.2f;
276 private const float Efwid = 0.0f;
277
278 // X component -- distance from zero to the front or back of a level
279 private const float Adep = 0f;
280 private const float Bdep = 0.3f;
281 private const float Cdep = 0.5f;
282 private const float Ddep = 0.2f;
283 private const float Edep = 0f;
284
285 private OMV.Vector3[] avatarVertices = {
286 new OMV.Vector3( 0.0f, -Awid, Aup), // A0
287 new OMV.Vector3( 0.0f, +Awid, Aup), // A3
288
289 new OMV.Vector3( 0.0f, -Bwid, Bup), // B0
290 new OMV.Vector3(+Bdep, -Bfwid, Bup), // B1
291 new OMV.Vector3(+Bdep, +Bfwid, Bup), // B2
292 new OMV.Vector3( 0.0f, +Bwid, Bup), // B3
293 new OMV.Vector3(-Bdep, +Bfwid, Bup), // B4
294 new OMV.Vector3(-Bdep, -Bfwid, Bup), // B5
295
296 new OMV.Vector3( 0.0f, -Cwid, Cup), // C0
297 new OMV.Vector3(+Cdep, -Cfwid, Cup), // C1
298 new OMV.Vector3(+Cdep, +Cfwid, Cup), // C2
299 new OMV.Vector3( 0.0f, +Cwid, Cup), // C3
300 new OMV.Vector3(-Cdep, +Cfwid, Cup), // C4
301 new OMV.Vector3(-Cdep, -Cfwid, Cup), // C5
302
303 new OMV.Vector3( 0.0f, -Dwid, Dup), // D0
304 new OMV.Vector3(+Ddep, -Dfwid, Dup), // D1
305 new OMV.Vector3(+Ddep, +Dfwid, Dup), // D2
306 new OMV.Vector3( 0.0f, +Dwid, Dup), // D3
307 new OMV.Vector3(-Ddep, +Dfwid, Dup), // D4
308 new OMV.Vector3(-Ddep, -Dfwid, Dup), // D5
309
310 new OMV.Vector3( 0.0f, -Ewid, Eup), // E0
311 new OMV.Vector3( 0.0f, +Ewid, Eup), // E3
312 };
313
314 // Offsets of the vertices in the vertices array
315 private enum Ind : int
316 {
317 A0, A3,
318 B0, B1, B2, B3, B4, B5,
319 C0, C1, C2, C3, C4, C5,
320 D0, D1, D2, D3, D4, D5,
321 E0, E3
322 }
323
324 // Comments specify trianges and quads in clockwise direction
325 private Ind[] avatarIndices = {
326 Ind.A0, Ind.B0, Ind.B1, // A0,B0,B1
327 Ind.A0, Ind.B1, Ind.B2, Ind.B2, Ind.A3, Ind.A0, // A0,B1,B2,A3
328 Ind.A3, Ind.B2, Ind.B3, // A3,B2,B3
329 Ind.A3, Ind.B3, Ind.B4, // A3,B3,B4
330 Ind.A3, Ind.B4, Ind.B5, Ind.B5, Ind.A0, Ind.A3, // A3,B4,B5,A0
331 Ind.A0, Ind.B5, Ind.B0, // A0,B5,B0
332
333 Ind.B0, Ind.C0, Ind.C1, Ind.C1, Ind.B1, Ind.B0, // B0,C0,C1,B1
334 Ind.B1, Ind.C1, Ind.C2, Ind.C2, Ind.B2, Ind.B1, // B1,C1,C2,B2
335 Ind.B2, Ind.C2, Ind.C3, Ind.C3, Ind.B3, Ind.B2, // B2,C2,C3,B3
336 Ind.B3, Ind.C3, Ind.C4, Ind.C4, Ind.B4, Ind.B3, // B3,C3,C4,B4
337 Ind.B4, Ind.C4, Ind.C5, Ind.C5, Ind.B5, Ind.B4, // B4,C4,C5,B5
338 Ind.B5, Ind.C5, Ind.C0, Ind.C0, Ind.B0, Ind.B5, // B5,C5,C0,B0
339
340 Ind.C0, Ind.D0, Ind.D1, Ind.D1, Ind.C1, Ind.C0, // C0,D0,D1,C1
341 Ind.C1, Ind.D1, Ind.D2, Ind.D2, Ind.C2, Ind.C1, // C1,D1,D2,C2
342 Ind.C2, Ind.D2, Ind.D3, Ind.D3, Ind.C3, Ind.C2, // C2,D2,D3,C3
343 Ind.C3, Ind.D3, Ind.D4, Ind.D4, Ind.C4, Ind.C3, // C3,D3,D4,C4
344 Ind.C4, Ind.D4, Ind.D5, Ind.D5, Ind.C5, Ind.C4, // C4,D4,D5,C5
345 Ind.C5, Ind.D5, Ind.D0, Ind.D0, Ind.C0, Ind.C5, // C5,D5,D0,C0
346
347 Ind.E0, Ind.D0, Ind.D1, // E0,D0,D1
348 Ind.E0, Ind.D1, Ind.D2, Ind.D2, Ind.E3, Ind.E0, // E0,D1,D2,E3
349 Ind.E3, Ind.D2, Ind.D3, // E3,D2,D3
350 Ind.E3, Ind.D3, Ind.D4, // E3,D3,D4
351 Ind.E3, Ind.D4, Ind.D5, Ind.D5, Ind.E0, Ind.E3, // E3,D4,D5,E0
352 Ind.E0, Ind.D5, Ind.D0, // E0,D5,D0
353
354 };
355
356}
208} 357}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
index 3ca756c..e4fecc3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -44,7 +44,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
44{ 44{
45 static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; 45 static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]";
46 46
47 BulletHeightMapInfo m_mapInfo = null; 47 BulletHMapInfo m_mapInfo = null;
48 48
49 // Constructor to build a default, flat heightmap terrain. 49 // Constructor to build a default, flat heightmap terrain.
50 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) 50 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
@@ -58,7 +58,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
58 { 58 {
59 initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; 59 initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION;
60 } 60 }
61 m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); 61 m_mapInfo = new BulletHMapInfo(id, initialMap);
62 m_mapInfo.minCoords = minTerrainCoords; 62 m_mapInfo.minCoords = minTerrainCoords;
63 m_mapInfo.maxCoords = maxTerrainCoords; 63 m_mapInfo.maxCoords = maxTerrainCoords;
64 m_mapInfo.terrainRegionBase = TerrainBase; 64 m_mapInfo.terrainRegionBase = TerrainBase;
@@ -72,7 +72,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
72 Vector3 minCoords, Vector3 maxCoords) 72 Vector3 minCoords, Vector3 maxCoords)
73 : base(physicsScene, regionBase, id) 73 : base(physicsScene, regionBase, id)
74 { 74 {
75 m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); 75 m_mapInfo = new BulletHMapInfo(id, initialMap);
76 m_mapInfo.minCoords = minCoords; 76 m_mapInfo.minCoords = minCoords;
77 m_mapInfo.maxCoords = maxCoords; 77 m_mapInfo.maxCoords = maxCoords;
78 m_mapInfo.minZ = minCoords.Z; 78 m_mapInfo.minZ = minCoords.Z;
@@ -91,13 +91,11 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
91 // Using the information in m_mapInfo, create the physical representation of the heightmap. 91 // Using the information in m_mapInfo, create the physical representation of the heightmap.
92 private void BuildHeightmapTerrain() 92 private void BuildHeightmapTerrain()
93 { 93 {
94 m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID,
95 m_mapInfo.minCoords, m_mapInfo.maxCoords,
96 m_mapInfo.heightMap, BSTerrainManager.TERRAIN_COLLISION_MARGIN);
97
98 // Create the terrain shape from the mapInfo 94 // Create the terrain shape from the mapInfo
99 m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), 95 m_mapInfo.terrainShape = PhysicsScene.PE.CreateTerrainShape( m_mapInfo.ID,
100 BSPhysicsShapeType.SHAPE_TERRAIN); 96 new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ,
97 m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin);
98
101 99
102 // The terrain object initial position is at the center of the object 100 // The terrain object initial position is at the center of the object
103 Vector3 centerPos; 101 Vector3 centerPos;
@@ -105,28 +103,26 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
105 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); 103 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
106 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); 104 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f);
107 105
108 m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID, 106 m_mapInfo.terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape,
109 BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr, 107 m_mapInfo.ID, centerPos, Quaternion.Identity);
110 m_mapInfo.ID, centerPos, Quaternion.Identity));
111 108
112 // Set current terrain attributes 109 // Set current terrain attributes
113 BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); 110 PhysicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction);
114 BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); 111 PhysicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction);
115 BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); 112 PhysicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution);
116 BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 113 PhysicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT);
117 114
118 // Return the new terrain to the world of physical objects 115 // Return the new terrain to the world of physical objects
119 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); 116 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_mapInfo.terrainBody);
120 117
121 // redo its bounding box now that it is in the world 118 // redo its bounding box now that it is in the world
122 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); 119 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_mapInfo.terrainBody);
123 120
124 BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr, 121 m_mapInfo.terrainBody.collisionType = CollisionType.Terrain;
125 (uint)CollisionFilterGroups.TerrainFilter, 122 m_mapInfo.terrainBody.ApplyCollisionMask(PhysicsScene);
126 (uint)CollisionFilterGroups.TerrainMask);
127 123
128 // Make it so the terrain will not move or be considered for movement. 124 // Make it so the terrain will not move or be considered for movement.
129 BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); 125 PhysicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION);
130 126
131 return; 127 return;
132 } 128 }
@@ -136,19 +132,18 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
136 { 132 {
137 if (m_mapInfo != null) 133 if (m_mapInfo != null)
138 { 134 {
139 if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) 135 if (m_mapInfo.terrainBody.HasPhysicalBody)
140 { 136 {
141 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); 137 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_mapInfo.terrainBody);
142 // Frees both the body and the shape. 138 // Frees both the body and the shape.
143 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); 139 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_mapInfo.terrainBody);
144 BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr);
145 } 140 }
146 } 141 }
147 m_mapInfo = null; 142 m_mapInfo = null;
148 } 143 }
149 144
150 // The passed position is relative to the base of the region. 145 // The passed position is relative to the base of the region.
151 public override float GetHeightAtXYZ(Vector3 pos) 146 public override float GetTerrainHeightAtXYZ(Vector3 pos)
152 { 147 {
153 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; 148 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
154 149
@@ -166,5 +161,11 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
166 } 161 }
167 return ret; 162 return ret;
168 } 163 }
164
165 // The passed position is relative to the base of the region.
166 public override float GetWaterLevelAtXYZ(Vector3 pos)
167 {
168 return PhysicsScene.SimpleWaterLevel;
169 }
169} 170}
170} 171}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 23fcfd3..2e9db39 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -62,11 +62,12 @@ public abstract class BSTerrainPhys : IDisposable
62 ID = id; 62 ID = id;
63 } 63 }
64 public abstract void Dispose(); 64 public abstract void Dispose();
65 public abstract float GetHeightAtXYZ(Vector3 pos); 65 public abstract float GetTerrainHeightAtXYZ(Vector3 pos);
66 public abstract float GetWaterLevelAtXYZ(Vector3 pos);
66} 67}
67 68
68// ========================================================================================== 69// ==========================================================================================
69public sealed class BSTerrainManager 70public sealed class BSTerrainManager : IDisposable
70{ 71{
71 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; 72 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
72 73
@@ -75,13 +76,12 @@ public sealed class BSTerrainManager
75 public const float HEIGHT_INITIALIZATION = 24.987f; 76 public const float HEIGHT_INITIALIZATION = 24.987f;
76 public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f; 77 public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
77 public const float HEIGHT_GETHEIGHT_RET = 24.765f; 78 public const float HEIGHT_GETHEIGHT_RET = 24.765f;
79 public const float WATER_HEIGHT_GETHEIGHT_RET = 19.998f;
78 80
79 // If the min and max height are equal, we reduce the min by this 81 // If the min and max height are equal, we reduce the min by this
80 // amount to make sure that a bounding box is built for the terrain. 82 // amount to make sure that a bounding box is built for the terrain.
81 public const float HEIGHT_EQUAL_FUDGE = 0.2f; 83 public const float HEIGHT_EQUAL_FUDGE = 0.2f;
82 84
83 public const float TERRAIN_COLLISION_MARGIN = 0.0f;
84
85 // Until the whole simulator is changed to pass us the region size, we rely on constants. 85 // Until the whole simulator is changed to pass us the region size, we rely on constants.
86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
87 87
@@ -122,25 +122,28 @@ public sealed class BSTerrainManager
122 MegaRegionParentPhysicsScene = null; 122 MegaRegionParentPhysicsScene = null;
123 } 123 }
124 124
125 public void Dispose()
126 {
127 ReleaseGroundPlaneAndTerrain();
128 }
129
125 // Create the initial instance of terrain and the underlying ground plane. 130 // Create the initial instance of terrain and the underlying ground plane.
126 // This is called from the initialization routine so we presume it is 131 // This is called from the initialization routine so we presume it is
127 // safe to call Bullet in real time. We hope no one is moving prims around yet. 132 // safe to call Bullet in real time. We hope no one is moving prims around yet.
128 public void CreateInitialGroundPlaneAndTerrain() 133 public void CreateInitialGroundPlaneAndTerrain()
129 { 134 {
130 // The ground plane is here to catch things that are trying to drop to negative infinity 135 // The ground plane is here to catch things that are trying to drop to negative infinity
131 BulletShape groundPlaneShape = new BulletShape( 136 BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
132 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), 137 m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
133 BSPhysicsShapeType.SHAPE_GROUNDPLANE); 138 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity);
134 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, 139
135 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, 140 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane);
136 Vector3.Zero, Quaternion.Identity)); 141 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane);
137 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr);
138 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr);
139 // Ground plane does not move 142 // Ground plane does not move
140 BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); 143 PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
141 // Everything collides with the ground plane. 144 // Everything collides with the ground plane.
142 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, 145 m_groundPlane.collisionType = CollisionType.Groundplane;
143 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); 146 m_groundPlane.ApplyCollisionMask(PhysicsScene);
144 147
145 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. 148 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
146 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); 149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
@@ -150,13 +153,13 @@ public sealed class BSTerrainManager
150 // Release all the terrain structures we might have allocated 153 // Release all the terrain structures we might have allocated
151 public void ReleaseGroundPlaneAndTerrain() 154 public void ReleaseGroundPlaneAndTerrain()
152 { 155 {
153 if (m_groundPlane.ptr != IntPtr.Zero) 156 if (m_groundPlane.HasPhysicalBody)
154 { 157 {
155 if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr)) 158 if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane))
156 { 159 {
157 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr); 160 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_groundPlane);
158 } 161 }
159 m_groundPlane.ptr = IntPtr.Zero; 162 m_groundPlane.Clear();
160 } 163 }
161 164
162 ReleaseTerrain(); 165 ReleaseTerrain();
@@ -165,17 +168,22 @@ public sealed class BSTerrainManager
165 // Release all the terrain we have allocated 168 // Release all the terrain we have allocated
166 public void ReleaseTerrain() 169 public void ReleaseTerrain()
167 { 170 {
168 foreach (KeyValuePair<Vector3, BSTerrainPhys> kvp in m_terrains) 171 lock (m_terrains)
169 { 172 {
170 kvp.Value.Dispose(); 173 foreach (KeyValuePair<Vector3, BSTerrainPhys> kvp in m_terrains)
174 {
175 kvp.Value.Dispose();
176 }
177 m_terrains.Clear();
171 } 178 }
172 m_terrains.Clear();
173 } 179 }
174 180
175 // The simulator wants to set a new heightmap for the terrain. 181 // The simulator wants to set a new heightmap for the terrain.
176 public void SetTerrain(float[] heightMap) { 182 public void SetTerrain(float[] heightMap) {
177 float[] localHeightMap = heightMap; 183 float[] localHeightMap = heightMap;
178 PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() 184 // If there are multiple requests for changes to the same terrain between ticks,
185 // only do that last one.
186 PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate()
179 { 187 {
180 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) 188 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
181 { 189 {
@@ -211,6 +219,7 @@ public sealed class BSTerrainManager
211 // terrain shape is created and added to the body. 219 // terrain shape is created and added to the body.
212 // This call is most often used to update the heightMap and parameters of the terrain. 220 // This call is most often used to update the heightMap and parameters of the terrain.
213 // (The above does suggest that some simplification/refactoring is in order.) 221 // (The above does suggest that some simplification/refactoring is in order.)
222 // Called during taint-time.
214 private void UpdateTerrain(uint id, float[] heightMap, 223 private void UpdateTerrain(uint id, float[] heightMap,
215 Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) 224 Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
216 { 225 {
@@ -220,7 +229,7 @@ public sealed class BSTerrainManager
220 // Find high and low points of passed heightmap. 229 // Find high and low points of passed heightmap.
221 // The min and max passed in is usually the area objects can be in (maximum 230 // The min and max passed in is usually the area objects can be in (maximum
222 // object height, for instance). The terrain wants the bounding box for the 231 // object height, for instance). The terrain wants the bounding box for the
223 // terrain so we replace passed min and max Z with the actual terrain min/max Z. 232 // terrain so replace passed min and max Z with the actual terrain min/max Z.
224 float minZ = float.MaxValue; 233 float minZ = float.MaxValue;
225 float maxZ = float.MinValue; 234 float maxZ = float.MinValue;
226 foreach (float height in heightMap) 235 foreach (float height in heightMap)
@@ -238,15 +247,15 @@ public sealed class BSTerrainManager
238 247
239 Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f); 248 Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f);
240 249
241 BSTerrainPhys terrainPhys; 250 lock (m_terrains)
242 if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys))
243 { 251 {
244 // There is already a terrain in this spot. Free the old and build the new. 252 BSTerrainPhys terrainPhys;
245 DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", 253 if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys))
246 BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords);
247
248 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:UpdateExisting", delegate()
249 { 254 {
255 // There is already a terrain in this spot. Free the old and build the new.
256 DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
257 BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords);
258
250 // Remove old terrain from the collection 259 // Remove old terrain from the collection
251 m_terrains.Remove(terrainRegionBase); 260 m_terrains.Remove(terrainRegionBase);
252 // Release any physical memory it may be using. 261 // Release any physical memory it may be using.
@@ -271,35 +280,24 @@ public sealed class BSTerrainManager
271 // I hate doing this, but just bail 280 // I hate doing this, but just bail
272 return; 281 return;
273 } 282 }
274 }); 283 }
275 } 284 else
276 else 285 {
277 { 286 // We don't know about this terrain so either we are creating a new terrain or
278 // We don't know about this terrain so either we are creating a new terrain or 287 // our mega-prim child is giving us a new terrain to add to the phys world
279 // our mega-prim child is giving us a new terrain to add to the phys world
280
281 // if this is a child terrain, calculate a unique terrain id
282 uint newTerrainID = id;
283 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
284 newTerrainID = ++m_terrainCount;
285
286 float[] heightMapX = heightMap;
287 Vector3 minCoordsX = minCoords;
288 Vector3 maxCoordsX = maxCoords;
289 288
290 DetailLog("{0},UpdateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", 289 // if this is a child terrain, calculate a unique terrain id
291 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); 290 uint newTerrainID = id;
291 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
292 newTerrainID = ++m_terrainCount;
292 293
293 // Code that must happen at taint-time 294 DetailLog("{0},UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
294 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:NewTerrain", delegate() 295 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
295 {
296 DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}",
297 BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y);
298 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); 296 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
299 m_terrains.Add(terrainRegionBase, newTerrainPhys); 297 m_terrains.Add(terrainRegionBase, newTerrainPhys);
300 298
301 m_terrainModified = true; 299 m_terrainModified = true;
302 }); 300 }
303 } 301 }
304 } 302 }
305 303
@@ -308,9 +306,9 @@ public sealed class BSTerrainManager
308 { 306 {
309 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", 307 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
310 LogHeader, PhysicsScene.RegionName, terrainRegionBase, 308 LogHeader, PhysicsScene.RegionName, terrainRegionBase,
311 (BSTerrainPhys.TerrainImplementation)PhysicsScene.Params.terrainImplementation); 309 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation);
312 BSTerrainPhys newTerrainPhys = null; 310 BSTerrainPhys newTerrainPhys = null;
313 switch ((int)PhysicsScene.Params.terrainImplementation) 311 switch ((int)BSParam.TerrainImplementation)
314 { 312 {
315 case (int)BSTerrainPhys.TerrainImplementation.Heightmap: 313 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
316 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, 314 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id,
@@ -323,14 +321,21 @@ public sealed class BSTerrainManager
323 default: 321 default:
324 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", 322 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
325 LogHeader, 323 LogHeader,
326 (int)PhysicsScene.Params.terrainImplementation, 324 (int)BSParam.TerrainImplementation,
327 PhysicsScene.Params.terrainImplementation, 325 BSParam.TerrainImplementation,
328 PhysicsScene.RegionName, terrainRegionBase); 326 PhysicsScene.RegionName, terrainRegionBase);
329 break; 327 break;
330 } 328 }
331 return newTerrainPhys; 329 return newTerrainPhys;
332 } 330 }
333 331
332 // Return 'true' of this position is somewhere in known physical terrain space
333 public bool IsWithinKnownTerrain(Vector3 pos)
334 {
335 Vector3 terrainBaseXYZ;
336 BSTerrainPhys physTerrain;
337 return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ);
338 }
334 339
335 // Given an X and Y, find the height of the terrain. 340 // Given an X and Y, find the height of the terrain.
336 // Since we could be handling multiple terrains for a mega-region, 341 // Since we could be handling multiple terrains for a mega-region,
@@ -341,40 +346,74 @@ public sealed class BSTerrainManager
341 private float lastHeightTX = 999999f; 346 private float lastHeightTX = 999999f;
342 private float lastHeightTY = 999999f; 347 private float lastHeightTY = 999999f;
343 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; 348 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
344 public float GetTerrainHeightAtXYZ(Vector3 loc) 349 public float GetTerrainHeightAtXYZ(Vector3 pos)
345 { 350 {
346 float tX = loc.X; 351 float tX = pos.X;
347 float tY = loc.Y; 352 float tY = pos.Y;
348 // You'd be surprized at the number of times this routine is called 353 // You'd be surprized at the number of times this routine is called
349 // with the same parameters as last time. 354 // with the same parameters as last time.
350 if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY) 355 if (!m_terrainModified && (lastHeightTX == tX) && (lastHeightTY == tY))
351 return lastHeight; 356 return lastHeight;
357 m_terrainModified = false;
352 358
353 lastHeightTX = tX; 359 lastHeightTX = tX;
354 lastHeightTY = tY; 360 lastHeightTY = tY;
355 float ret = HEIGHT_GETHEIGHT_RET; 361 float ret = HEIGHT_GETHEIGHT_RET;
356 362
357 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; 363 Vector3 terrainBaseXYZ;
358 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
359 Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);
360
361 BSTerrainPhys physTerrain; 364 BSTerrainPhys physTerrain;
362 if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain)) 365 if (GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ))
363 { 366 {
364 ret = physTerrain.GetHeightAtXYZ(loc - terrainBaseXYZ); 367 ret = physTerrain.GetTerrainHeightAtXYZ(pos - terrainBaseXYZ);
365 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,loc={1},base={2},height={3}",
366 BSScene.DetailLogZero, loc, terrainBaseXYZ, ret);
367 } 368 }
368 else 369 else
369 { 370 {
370 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", 371 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
371 LogHeader, PhysicsScene.RegionName, tX, tY); 372 LogHeader, PhysicsScene.RegionName, tX, tY);
373 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}",
374 BSScene.DetailLogZero, pos, terrainBaseXYZ);
372 } 375 }
373 m_terrainModified = false; 376
374 lastHeight = ret; 377 lastHeight = ret;
375 return ret; 378 return ret;
376 } 379 }
377 380
381 public float GetWaterLevelAtXYZ(Vector3 pos)
382 {
383 float ret = WATER_HEIGHT_GETHEIGHT_RET;
384
385 Vector3 terrainBaseXYZ;
386 BSTerrainPhys physTerrain;
387 if (GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ))
388 {
389 ret = physTerrain.GetWaterLevelAtXYZ(pos);
390 }
391 else
392 {
393 PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}",
394 LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret);
395 }
396 return ret;
397 }
398
399 // Given an address, return 'true' of there is a description of that terrain and output
400 // the descriptor class and the 'base' fo the addresses therein.
401 private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase)
402 {
403 int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
404 int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
405 Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);
406
407 BSTerrainPhys physTerrain = null;
408 lock (m_terrains)
409 {
410 m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain);
411 }
412 outTerrainBase = terrainBaseXYZ;
413 outPhysTerrain = physTerrain;
414 return (physTerrain != null);
415 }
416
378 // Although no one seems to check this, I do support combining. 417 // Although no one seems to check this, I do support combining.
379 public bool SupportsCombining() 418 public bool SupportsCombining()
380 { 419 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
index dca7150..d7e800d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -88,15 +88,15 @@ public sealed class BSTerrainMesh : BSTerrainPhys
88 // Something is very messed up and a crash is in our future. 88 // Something is very messed up and a crash is in our future.
89 return; 89 return;
90 } 90 }
91 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}",
92 ID, indicesCount, indices.Length, verticesCount, vertices.Length);
91 93
92 m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, 94 m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices);
93 indicesCount, indices, verticesCount, vertices), 95 if (!m_terrainShape.HasPhysicalShape)
94 BSPhysicsShapeType.SHAPE_MESH);
95 if (m_terrainShape.ptr == IntPtr.Zero)
96 { 96 {
97 // DISASTER!! 97 // DISASTER!!
98 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); 98 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID);
99 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); 99 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
100 // Something is very messed up and a crash is in our future. 100 // Something is very messed up and a crash is in our future.
101 return; 101 return;
102 } 102 }
@@ -104,49 +104,56 @@ public sealed class BSTerrainMesh : BSTerrainPhys
104 Vector3 pos = regionBase; 104 Vector3 pos = regionBase;
105 Quaternion rot = Quaternion.Identity; 105 Quaternion rot = Quaternion.Identity;
106 106
107 m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot)); 107 m_terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot);
108 if (m_terrainBody.ptr == IntPtr.Zero) 108 if (!m_terrainBody.HasPhysicalBody)
109 { 109 {
110 // DISASTER!! 110 // DISASTER!!
111 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); 111 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
112 // Something is very messed up and a crash is in our future. 112 // Something is very messed up and a crash is in our future.
113 return; 113 return;
114 } 114 }
115 115
116 // Set current terrain attributes 116 // Set current terrain attributes
117 BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); 117 PhysicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
118 BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); 118 PhysicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
119 BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution); 119 PhysicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
120 BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 120 PhysicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);
121 121
122 // Static objects are not very massive. 122 // Static objects are not very massive.
123 BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero); 123 PhysicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero);
124 124
125 // Return the new terrain to the world of physical objects 125 // Put the new terrain to the world of physical objects
126 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); 126 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_terrainBody);
127 127
128 // redo its bounding box now that it is in the world 128 // Redo its bounding box now that it is in the world
129 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); 129 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_terrainBody);
130 130
131 BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr, 131 m_terrainBody.collisionType = CollisionType.Terrain;
132 (uint)CollisionFilterGroups.TerrainFilter, 132 m_terrainBody.ApplyCollisionMask(PhysicsScene);
133 (uint)CollisionFilterGroups.TerrainMask); 133
134 if (BSParam.UseSingleSidedMeshes)
135 {
136 PhysicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial", id);
137 PhysicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
138 }
134 139
135 // Make it so the terrain will not move or be considered for movement. 140 // Make it so the terrain will not move or be considered for movement.
136 BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION); 141 PhysicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION);
137 } 142 }
138 143
139 public override void Dispose() 144 public override void Dispose()
140 { 145 {
141 if (m_terrainBody.ptr != IntPtr.Zero) 146 if (m_terrainBody.HasPhysicalBody)
142 { 147 {
143 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); 148 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_terrainBody);
144 // Frees both the body and the shape. 149 // Frees both the body and the shape.
145 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr); 150 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_terrainBody);
151 m_terrainBody.Clear();
152 m_terrainShape.Clear();
146 } 153 }
147 } 154 }
148 155
149 public override float GetHeightAtXYZ(Vector3 pos) 156 public override float GetTerrainHeightAtXYZ(Vector3 pos)
150 { 157 {
151 // For the moment use the saved heightmap to get the terrain height. 158 // For the moment use the saved heightmap to get the terrain height.
152 // TODO: raycast downward to find the true terrain below the position. 159 // TODO: raycast downward to find the true terrain below the position.
@@ -167,10 +174,15 @@ public sealed class BSTerrainMesh : BSTerrainPhys
167 return ret; 174 return ret;
168 } 175 }
169 176
177 // The passed position is relative to the base of the region.
178 public override float GetWaterLevelAtXYZ(Vector3 pos)
179 {
180 return PhysicsScene.SimpleWaterLevel;
181 }
182
170 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). 183 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
171 // Return 'true' if successfully created. 184 // Return 'true' if successfully created.
172 public static bool ConvertHeightmapToMesh( 185 public static bool ConvertHeightmapToMesh( BSScene physicsScene,
173 BSScene physicsScene,
174 float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap 186 float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap
175 float extentX, float extentY, // zero based range for output vertices 187 float extentX, float extentY, // zero based range for output vertices
176 Vector3 extentBase, // base to be added to all vertices 188 Vector3 extentBase, // base to be added to all vertices
@@ -188,6 +200,11 @@ public sealed class BSTerrainMesh : BSTerrainPhys
188 // Simple mesh creation which assumes magnification == 1. 200 // Simple mesh creation which assumes magnification == 1.
189 // TODO: do a more general solution that scales, adds new vertices and smoothes the result. 201 // TODO: do a more general solution that scales, adds new vertices and smoothes the result.
190 202
203 // Create an array of vertices that is sizeX+1 by sizeY+1 (note the loop
204 // from zero to <= sizeX). The triangle indices are then generated as two triangles
205 // per heightmap point. There are sizeX by sizeY of these squares. The extra row and
206 // column of vertices are used to complete the triangles of the last row and column
207 // of the heightmap.
191 try 208 try
192 { 209 {
193 // One vertice per heightmap value plus the vertices off the top and bottom edge. 210 // One vertice per heightmap value plus the vertices off the top and bottom edge.
@@ -200,16 +217,18 @@ public sealed class BSTerrainMesh : BSTerrainPhys
200 float magY = (float)sizeY / extentY; 217 float magY = (float)sizeY / extentY;
201 physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", 218 physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}",
202 BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY); 219 BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY);
220 float minHeight = float.MaxValue;
203 // Note that sizeX+1 vertices are created since there is land between this and the next region. 221 // Note that sizeX+1 vertices are created since there is land between this and the next region.
204 for (int yy = 0; yy <= sizeY; yy++) 222 for (int yy = 0; yy <= sizeY; yy++)
205 { 223 {
206 for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we got through sizeX + 1 times 224 for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we go around sizeX + 1 times
207 { 225 {
208 int offset = yy * sizeX + xx; 226 int offset = yy * sizeX + xx;
209 // Extend the height from the height from the last row or column 227 // Extend the height with the height from the last row or column
210 if (yy == sizeY) offset -= sizeX; 228 if (yy == sizeY) offset -= sizeX;
211 if (xx == sizeX) offset -= 1; 229 if (xx == sizeX) offset -= 1;
212 float height = heightMap[offset]; 230 float height = heightMap[offset];
231 minHeight = Math.Min(minHeight, height);
213 vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; 232 vertices[verticesCount + 0] = (float)xx * magX + extentBase.X;
214 vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; 233 vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y;
215 vertices[verticesCount + 2] = height + extentBase.Z; 234 vertices[verticesCount + 2] = height + extentBase.Z;
@@ -217,14 +236,12 @@ public sealed class BSTerrainMesh : BSTerrainPhys
217 } 236 }
218 } 237 }
219 verticesCount = verticesCount / 3; 238 verticesCount = verticesCount / 3;
220 physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeVerts,verCount={1}",
221 BSScene.DetailLogZero, verticesCount);
222 239
223 for (int yy = 0; yy < sizeY; yy++) 240 for (int yy = 0; yy < sizeY; yy++)
224 { 241 {
225 for (int xx = 0; xx < sizeX; xx++) 242 for (int xx = 0; xx < sizeX; xx++)
226 { 243 {
227 int offset = yy * sizeX + xx; 244 int offset = yy * (sizeX + 1) + xx;
228 // Each vertices is presumed to be the upper left corner of a box of two triangles 245 // Each vertices is presumed to be the upper left corner of a box of two triangles
229 indices[indicesCount + 0] = offset; 246 indices[indicesCount + 0] = offset;
230 indices[indicesCount + 1] = offset + 1; 247 indices[indicesCount + 1] = offset + 1;
@@ -235,8 +252,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
235 indicesCount += 6; 252 indicesCount += 6;
236 } 253 }
237 } 254 }
238 physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeIndices,indCount={1}", // DEEBUG DEBUG DEBUG 255
239 LogHeader, indicesCount); // DEBUG
240 ret = true; 256 ret = true;
241 } 257 }
242 catch (Exception e) 258 catch (Exception e)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
deleted file mode 100644
index e60a760..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ /dev/null
@@ -1,1015 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Runtime.InteropServices;
29using System.Security;
30using System.Text;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin {
34
35// Classes to allow some type checking for the API
36// These hold pointers to allocated objects in the unmanaged space.
37
38// The physics engine controller class created at initialization
39public struct BulletSim
40{
41 public BulletSim(uint worldId, BSScene bss, IntPtr xx)
42 {
43 ptr = xx;
44 worldID = worldId;
45 physicsScene = bss;
46 }
47 public IntPtr ptr;
48 public uint worldID;
49 // The scene is only in here so very low level routines have a handle to print debug/error messages
50 public BSScene physicsScene;
51}
52
53// An allocated Bullet btRigidBody
54public struct BulletBody
55{
56 public BulletBody(uint id, IntPtr xx)
57 {
58 ID = id;
59 ptr = xx;
60 collisionFilter = 0;
61 collisionMask = 0;
62 }
63 public IntPtr ptr;
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=BSPhysicsShapeType.SHAPE_UNKNOWN;
92 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
93 isNativeShape = false;
94 }
95 public BulletShape(IntPtr xx, BSPhysicsShapeType typ)
96 {
97 ptr = xx;
98 type = typ;
99 shapeKey = 0;
100 isNativeShape = false;
101 }
102 public IntPtr ptr;
103 public BSPhysicsShapeType type;
104 public System.UInt64 shapeKey;
105 public bool isNativeShape;
106 public override string ToString()
107 {
108 StringBuilder buff = new StringBuilder();
109 buff.Append("<p=");
110 buff.Append(ptr.ToString("X"));
111 buff.Append(",s=");
112 buff.Append(type.ToString());
113 buff.Append(",k=");
114 buff.Append(shapeKey.ToString("X"));
115 buff.Append(",n=");
116 buff.Append(isNativeShape.ToString());
117 buff.Append(">");
118 return buff.ToString();
119 }
120}
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
136public struct BulletConstraint
137{
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 = Vector3.Zero;
156 minCoords = new Vector3(100f, 100f, 25f);
157 maxCoords = new Vector3(101f, 101f, 26f);
158 minZ = maxZ = 0f;
159 sizeX = sizeY = 256f;
160 }
161 public uint ID;
162 public IntPtr Ptr;
163 public float[] heightMap;
164 public Vector3 terrainRegionBase;
165 public Vector3 minCoords;
166 public Vector3 maxCoords;
167 public float sizeX, sizeY;
168 public float minZ, maxZ;
169 public BulletShape terrainShape;
170 public BulletBody terrainBody;
171}
172
173// ===============================================================================
174[StructLayout(LayoutKind.Sequential)]
175public struct ConvexHull
176{
177 Vector3 Offset;
178 int VertexCount;
179 Vector3[] Vertices;
180}
181public enum BSPhysicsShapeType
182{
183 SHAPE_UNKNOWN = 0,
184 SHAPE_CAPSULE = 1,
185 SHAPE_BOX = 2,
186 SHAPE_CONE = 3,
187 SHAPE_CYLINDER = 4,
188 SHAPE_SPHERE = 5,
189 SHAPE_MESH = 6,
190 SHAPE_HULL = 7,
191 // following defined by BulletSim
192 SHAPE_GROUNDPLANE = 20,
193 SHAPE_TERRAIN = 21,
194 SHAPE_COMPOUND = 22,
195 SHAPE_HEIGHTMAP = 23,
196};
197
198// The native shapes have predefined shape hash keys
199public enum FixedShapeKey : ulong
200{
201 KEY_NONE = 0,
202 KEY_BOX = 1,
203 KEY_SPHERE = 2,
204 KEY_CONE = 3,
205 KEY_CYLINDER = 4,
206 KEY_CAPSULE = 5,
207}
208
209[StructLayout(LayoutKind.Sequential)]
210public struct ShapeData
211{
212 public uint ID;
213 public BSPhysicsShapeType Type;
214 public Vector3 Position;
215 public Quaternion Rotation;
216 public Vector3 Velocity;
217 public Vector3 Scale;
218 public float Mass;
219 public float Buoyancy;
220 public System.UInt64 HullKey;
221 public System.UInt64 MeshKey;
222 public float Friction;
223 public float Restitution;
224 public float Collidable; // true of things bump into this
225 public float Static; // true if a static object. Otherwise gravity, etc.
226 public float Solid; // true if object cannot be passed through
227 public Vector3 Size;
228
229 // note that bools are passed as floats since bool size changes by language and architecture
230 public const float numericTrue = 1f;
231 public const float numericFalse = 0f;
232}
233[StructLayout(LayoutKind.Sequential)]
234public struct SweepHit
235{
236 public uint ID;
237 public float Fraction;
238 public Vector3 Normal;
239 public Vector3 Point;
240}
241[StructLayout(LayoutKind.Sequential)]
242public struct RaycastHit
243{
244 public uint ID;
245 public float Fraction;
246 public Vector3 Normal;
247}
248[StructLayout(LayoutKind.Sequential)]
249public struct CollisionDesc
250{
251 public uint aID;
252 public uint bID;
253 public Vector3 point;
254 public Vector3 normal;
255}
256[StructLayout(LayoutKind.Sequential)]
257public struct EntityProperties
258{
259 public uint ID;
260 public Vector3 Position;
261 public Quaternion Rotation;
262 public Vector3 Velocity;
263 public Vector3 Acceleration;
264 public Vector3 RotationalVelocity;
265}
266
267// Format of this structure must match the definition in the C++ code
268[StructLayout(LayoutKind.Sequential)]
269public struct ConfigurationParameters
270{
271 public float defaultFriction;
272 public float defaultDensity;
273 public float defaultRestitution;
274 public float collisionMargin;
275 public float gravity;
276
277 public float linearDamping;
278 public float angularDamping;
279 public float deactivationTime;
280 public float linearSleepingThreshold;
281 public float angularSleepingThreshold;
282 public float ccdMotionThreshold;
283 public float ccdSweptSphereRadius;
284 public float contactProcessingThreshold;
285
286 public float terrainImplementation;
287 public float terrainFriction;
288 public float terrainHitFraction;
289 public float terrainRestitution;
290 public float avatarFriction;
291 public float avatarStandingFriction;
292 public float avatarDensity;
293 public float avatarRestitution;
294 public float avatarCapsuleWidth;
295 public float avatarCapsuleDepth;
296 public float avatarCapsuleHeight;
297 public float avatarContactProcessingThreshold;
298
299 public float maxPersistantManifoldPoolSize;
300 public float maxCollisionAlgorithmPoolSize;
301 public float shouldDisableContactPoolDynamicAllocation;
302 public float shouldForceUpdateAllAabbs;
303 public float shouldRandomizeSolverOrder;
304 public float shouldSplitSimulationIslands;
305 public float shouldEnableFrictionCaching;
306 public float numberOfSolverIterations;
307
308 public float linksetImplementation;
309 public float linkConstraintUseFrameOffset;
310 public float linkConstraintEnableTransMotor;
311 public float linkConstraintTransMotorMaxVel;
312 public float linkConstraintTransMotorMaxForce;
313 public float linkConstraintERP;
314 public float linkConstraintCFM;
315 public float linkConstraintSolverIterations;
316
317 public float physicsLoggingFrames;
318
319 public const float numericTrue = 1f;
320 public const float numericFalse = 0f;
321}
322
323
324// The states a bullet collision object can have
325public enum ActivationState : uint
326{
327 ACTIVE_TAG = 1,
328 ISLAND_SLEEPING,
329 WANTS_DEACTIVATION,
330 DISABLE_DEACTIVATION,
331 DISABLE_SIMULATION,
332}
333
334public enum CollisionObjectTypes : int
335{
336 CO_COLLISION_OBJECT = 1 << 0,
337 CO_RIGID_BODY = 1 << 1,
338 CO_GHOST_OBJECT = 1 << 2,
339 CO_SOFT_BODY = 1 << 3,
340 CO_HF_FLUID = 1 << 4,
341 CO_USER_TYPE = 1 << 5,
342}
343
344// Values used by Bullet and BulletSim to control object properties.
345// Bullet's "CollisionFlags" has more to do with operations on the
346// object (if collisions happen, if gravity effects it, ...).
347public enum CollisionFlags : uint
348{
349 CF_STATIC_OBJECT = 1 << 0,
350 CF_KINEMATIC_OBJECT = 1 << 1,
351 CF_NO_CONTACT_RESPONSE = 1 << 2,
352 CF_CUSTOM_MATERIAL_CALLBACK = 1 << 3,
353 CF_CHARACTER_OBJECT = 1 << 4,
354 CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
355 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
356 // Following used by BulletSim to control collisions
357 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
358 BS_FLOATS_ON_WATER = 1 << 11,
359 BS_NONE = 0,
360 BS_ALL = 0xFFFFFFFF,
361
362 // These are the collision flags switched depending on physical state.
363 // The other flags are used for other things and should not be fooled with.
364 BS_ACTIVE = CF_STATIC_OBJECT
365 | CF_KINEMATIC_OBJECT
366 | CF_NO_CONTACT_RESPONSE
367};
368
369// Values for collisions groups and masks
370public enum CollisionFilterGroups : uint
371{
372 // Don't use the bit definitions!! Define the use in a
373 // filter/mask definition below. This way collision interactions
374 // are more easily debugged.
375 BNoneFilter = 0,
376 BDefaultFilter = 1 << 0,
377 BStaticFilter = 1 << 1,
378 BKinematicFilter = 1 << 2,
379 BDebrisFilter = 1 << 3,
380 BSensorTrigger = 1 << 4,
381 BCharacterFilter = 1 << 5,
382 BAllFilter = 0xFFFFFFFF,
383 // Filter groups defined by BulletSim
384 BGroundPlaneFilter = 1 << 10,
385 BTerrainFilter = 1 << 11,
386 BRaycastFilter = 1 << 12,
387 BSolidFilter = 1 << 13,
388 BLinksetFilter = 1 << 14,
389
390 // The collsion filters and masked are defined in one place -- don't want them scattered
391 AvatarFilter = BCharacterFilter,
392 AvatarMask = BAllFilter,
393 ObjectFilter = BSolidFilter,
394 ObjectMask = BAllFilter,
395 StaticObjectFilter = BStaticFilter,
396 StaticObjectMask = BAllFilter & ~BStaticFilter, // static objects don't collide with each other
397 LinksetFilter = BLinksetFilter,
398 LinksetMask = BAllFilter & ~BLinksetFilter, // linkset objects don't collide with each other
399 VolumeDetectFilter = BSensorTrigger,
400 VolumeDetectMask = ~BSensorTrigger,
401 TerrainFilter = BTerrainFilter,
402 TerrainMask = BAllFilter & ~BStaticFilter, // static objects on the ground don't collide
403 GroundPlaneFilter = BGroundPlaneFilter,
404 GroundPlaneMask = BAllFilter
405
406};
407
408// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
409// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
410public enum ConstraintParams : int
411{
412 BT_CONSTRAINT_ERP = 1, // this one is not used in Bullet as of 20120730
413 BT_CONSTRAINT_STOP_ERP,
414 BT_CONSTRAINT_CFM,
415 BT_CONSTRAINT_STOP_CFM,
416};
417public enum ConstraintParamAxis : int
418{
419 AXIS_LINEAR_X = 0,
420 AXIS_LINEAR_Y,
421 AXIS_LINEAR_Z,
422 AXIS_ANGULAR_X,
423 AXIS_ANGULAR_Y,
424 AXIS_ANGULAR_Z,
425 AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls
426 AXIS_ANGULAR_ALL,
427 AXIS_ALL
428};
429
430// ===============================================================================
431static class BulletSimAPI {
432
433// Link back to the managed code for outputting log messages
434[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
435public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
436
437// ===============================================================================
438// Initialization and simulation
439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
440public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
441 int maxCollisions, IntPtr collisionArray,
442 int maxUpdates, IntPtr updateArray,
443 DebugLogCallback logRoutine);
444
445[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
446public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
447
448[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
449public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
450
451[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
452public static extern void Shutdown2(IntPtr sim);
453
454[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
455public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
456 out int updatedEntityCount,
457 out IntPtr updatedEntitiesPtr,
458 out int collidersCount,
459 out IntPtr collidersPtr);
460
461[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
462public static extern bool PushUpdate2(IntPtr obj);
463
464// =====================================================================================
465// Mesh, hull, shape and body creation helper routines
466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
467public static extern IntPtr CreateMeshShape2(IntPtr world,
468 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
469 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
470
471[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
472public static extern IntPtr CreateHullShape2(IntPtr world,
473 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
474
475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
476public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
477
478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
479public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
480
481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
482public static extern bool IsNativeShape2(IntPtr shape);
483
484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
485public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
486
487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
488public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree);
489
490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
491public static extern int GetNumberOfCompoundChildren2(IntPtr cShape);
492
493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
494public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
495
496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
497public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
498
499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
500public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
501
502[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
503public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
504
505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
506public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape);
507
508[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
509public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id);
510
511[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
512public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, uint id, IntPtr constructionInfo);
513
514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
515public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
516
517[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
518public static extern int GetBodyType2(IntPtr obj);
519
520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
521public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
522
523[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
524public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot);
525
526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
527public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
528
529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
530public static extern IntPtr AllocateBodyInfo2(IntPtr obj);
531
532[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
533public static extern void ReleaseBodyInfo2(IntPtr obj);
534
535[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
536public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
537
538// =====================================================================================
539// Terrain creation and helper routines
540[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
541public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
542 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
543
544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
545public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords,
546 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
547
548[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
549public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo);
550
551[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
552public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
553
554[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
555public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo);
556
557// =====================================================================================
558// Constraint creation and helper routines
559[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
560public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
561 Vector3 frame1loc, Quaternion frame1rot,
562 Vector3 frame2loc, Quaternion frame2rot,
563 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
564
565[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
566public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2,
567 Vector3 joinPoint,
568 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
569
570[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
571public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
572 Vector3 pivotinA, Vector3 pivotinB,
573 Vector3 axisInA, Vector3 axisInB,
574 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
575
576[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
577public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
578
579[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
580public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
581
582[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
583public static extern bool SetFrames2(IntPtr constrain,
584 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
585
586[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
587public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
588
589[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
590public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
591
592[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
593public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
594
595[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
596public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
597
598[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
599public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
600
601[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
602public static extern bool CalculateTransforms2(IntPtr constrain);
603
604[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
605public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
606
607[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
608public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
609
610// =====================================================================================
611// btCollisionWorld entries
612[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
613public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj);
614
615[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
616public static extern void UpdateAabbs2(IntPtr world);
617
618[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
619public static extern bool GetForceUpdateAllAabbs2(IntPtr world);
620
621[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
622public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force);
623
624// =====================================================================================
625// btDynamicsWorld entries
626[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
627public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
628
629[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
630public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
631
632[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
633public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
634
635[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
636public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain);
637// =====================================================================================
638// btCollisionObject entries
639[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
640public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain);
641
642[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
643public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict);
644
645[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
646public static extern bool HasAnisotripicFriction2(IntPtr constrain);
647
648[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
649public static extern void SetContactProcessingThreshold2(IntPtr obj, float val);
650
651[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
652public static extern float GetContactProcessingThreshold2(IntPtr obj);
653
654[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
655public static extern bool IsStaticObject2(IntPtr obj);
656
657[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
658public static extern bool IsKinematicObject2(IntPtr obj);
659
660[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
661public static extern bool IsStaticOrKinematicObject2(IntPtr obj);
662
663[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
664public static extern bool HasContactResponse2(IntPtr obj);
665
666[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
667public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape);
668
669[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
670public static extern IntPtr GetCollisionShape2(IntPtr obj);
671
672[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
673public static extern int GetActivationState2(IntPtr obj);
674
675[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
676public static extern void SetActivationState2(IntPtr obj, int state);
677
678[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
679public static extern void SetDeactivationTime2(IntPtr obj, float dtime);
680
681[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
682public static extern float GetDeactivationTime2(IntPtr obj);
683
684[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
685public static extern void ForceActivationState2(IntPtr obj, ActivationState state);
686
687[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
688public static extern void Activate2(IntPtr obj, bool forceActivation);
689
690[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
691public static extern bool IsActive2(IntPtr obj);
692
693[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
694public static extern void SetRestitution2(IntPtr obj, float val);
695
696[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
697public static extern float GetRestitution2(IntPtr obj);
698
699[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
700public static extern void SetFriction2(IntPtr obj, float val);
701
702[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
703public static extern float GetFriction2(IntPtr obj);
704
705 /* Haven't defined the type 'Transform'
706[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
707public static extern Transform GetWorldTransform2(IntPtr obj);
708
709[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
710public static extern void setWorldTransform2(IntPtr obj, Transform trans);
711 */
712
713[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
714public static extern Vector3 GetPosition2(IntPtr obj);
715
716[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
717public static extern Quaternion GetOrientation2(IntPtr obj);
718
719[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
720public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
721
722[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
723public static extern IntPtr GetBroadphaseHandle2(IntPtr obj);
724
725[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
726public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle);
727
728 /*
729[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
730public static extern Transform GetInterpolationWorldTransform2(IntPtr obj);
731
732[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
733public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans);
734 */
735
736[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
737public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel);
738
739[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
740public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel);
741
742[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
743public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel);
744
745[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
746public static extern float GetHitFraction2(IntPtr obj);
747
748[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
749public static extern void SetHitFraction2(IntPtr obj, float val);
750
751[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
752public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
753
754[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
755public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
756
757[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
758public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
759
760[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
761public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
762
763[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
764public static extern float GetCcdMotionThreshold2(IntPtr obj);
765
766[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
767public static extern void SetCcdMotionThreshold2(IntPtr obj, float val);
768
769[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
770public static extern float GetCcdSweptSphereRadius2(IntPtr obj);
771
772[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
773public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val);
774
775[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
776public static extern IntPtr GetUserPointer2(IntPtr obj);
777
778[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
779public static extern void SetUserPointer2(IntPtr obj, IntPtr val);
780
781// =====================================================================================
782// btRigidBody entries
783[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
784public static extern void ApplyGravity2(IntPtr obj);
785
786[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
787public static extern void SetGravity2(IntPtr obj, Vector3 val);
788
789[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
790public static extern Vector3 GetGravity2(IntPtr obj);
791
792[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
793public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
794
795[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
796public static extern void SetLinearDamping2(IntPtr obj, float lin_damping);
797
798[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
799public static extern void SetAngularDamping2(IntPtr obj, float ang_damping);
800
801[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
802public static extern float GetLinearDamping2(IntPtr obj);
803
804[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
805public static extern float GetAngularDamping2(IntPtr obj);
806
807[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
808public static extern float GetLinearSleepingThreshold2(IntPtr obj);
809
810[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
811public static extern float GetAngularSleepingThreshold2(IntPtr obj);
812
813[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
814public static extern void ApplyDamping2(IntPtr obj, float timeStep);
815
816[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
817public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
818
819[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
820public static extern Vector3 GetLinearFactor2(IntPtr obj);
821
822[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
823public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor);
824
825 /*
826[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
827public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans);
828 */
829
830[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
831public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot);
832
833// Add a force to the object as if its mass is one.
834[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
835public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force);
836
837// Set the force being applied to the object as if its mass is one.
838[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
839public static extern void SetObjectForce2(IntPtr obj, Vector3 force);
840
841[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
842public static extern Vector3 GetTotalForce2(IntPtr obj);
843
844[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
845public static extern Vector3 GetTotalTorque2(IntPtr obj);
846
847[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
848public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj);
849
850[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
851public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert);
852
853[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
854public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
855
856[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
857public static extern void ApplyTorque2(IntPtr obj, Vector3 torque);
858
859// Apply force at the given point. Will add torque to the object.
860[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
861public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos);
862
863// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
864[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
865public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp);
866
867// Apply impulse to the object's torque. Force is scaled by object's mass.
868[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
869public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp);
870
871// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
872[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
873public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos);
874
875[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
876public static extern void ClearForces2(IntPtr obj);
877
878[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
879public static extern void ClearAllForces2(IntPtr obj);
880
881[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
882public static extern void UpdateInertiaTensor2(IntPtr obj);
883
884[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
885public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj);
886
887 /*
888[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
889public static extern Transform GetCenterOfMassTransform2(IntPtr obj);
890 */
891
892[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
893public static extern Vector3 GetLinearVelocity2(IntPtr obj);
894
895[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
896public static extern Vector3 GetAngularVelocity2(IntPtr obj);
897
898[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
899public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val);
900
901[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
902public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
903
904[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
905public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos);
906
907[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
908public static extern void Translate2(IntPtr obj, Vector3 trans);
909
910[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
911public static extern void UpdateDeactivation2(IntPtr obj, float timeStep);
912
913[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
914public static extern bool WantsSleeping2(IntPtr obj);
915
916[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
917public static extern void SetAngularFactor2(IntPtr obj, float factor);
918
919[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
920public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor);
921
922[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
923public static extern Vector3 GetAngularFactor2(IntPtr obj);
924
925[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
926public static extern bool IsInWorld2(IntPtr obj);
927
928[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
929public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain);
930
931[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
932public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain);
933
934[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
935public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
936
937[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
938public static extern int GetNumConstraintRefs2(IntPtr obj);
939
940[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
941public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
942
943// =====================================================================================
944// btCollisionShape entries
945
946[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
947public static extern float GetAngularMotionDisc2(IntPtr shape);
948
949[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
950public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor);
951
952[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
953public static extern bool IsPolyhedral2(IntPtr shape);
954
955[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
956public static extern bool IsConvex2d2(IntPtr shape);
957
958[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
959public static extern bool IsConvex2(IntPtr shape);
960
961[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
962public static extern bool IsNonMoving2(IntPtr shape);
963
964[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
965public static extern bool IsConcave2(IntPtr shape);
966
967[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
968public static extern bool IsCompound2(IntPtr shape);
969
970[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
971public static extern bool IsSoftBody2(IntPtr shape);
972
973[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
974public static extern bool IsInfinite2(IntPtr shape);
975
976[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
977public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale);
978
979[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
980public static extern Vector3 GetLocalScaling2(IntPtr shape);
981
982[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
983public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass);
984
985[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
986public static extern int GetShapeType2(IntPtr shape);
987
988[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
989public static extern void SetMargin2(IntPtr shape, float val);
990
991[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
992public static extern float GetMargin2(IntPtr shape);
993
994// =====================================================================================
995// Debugging
996[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
997public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
998
999[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1000public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
1001
1002[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1003public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
1004
1005[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1006public static extern void DumpAllInfo2(IntPtr sim);
1007
1008[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1009public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
1010
1011[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1012public static extern void DumpPhysicsStatistics2(IntPtr sim);
1013
1014}
1015}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
new file mode 100755
index 0000000..8012d91
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
@@ -0,0 +1,269 @@
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;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34// Classes to allow some type checking for the API
35// These hold pointers to allocated objects in the unmanaged space.
36// These classes are subclassed by the various physical implementations of
37// objects. In particular, there is a version for physical instances in
38// unmanaged memory ("unman") and one for in managed memory ("XNA").
39
40// Currently, the instances of these classes are a reference to a
41// physical representation and this has no releationship to other
42// instances. Someday, refarb the usage of these classes so each instance
43// refers to a particular physical instance and this class controls reference
44// counts and such. This should be done along with adding BSShapes.
45
46public class BulletWorld
47{
48 public BulletWorld(uint worldId, BSScene bss)
49 {
50 worldID = worldId;
51 physicsScene = bss;
52 }
53 public uint worldID;
54 // The scene is only in here so very low level routines have a handle to print debug/error messages
55 public BSScene physicsScene;
56}
57
58// An allocated Bullet btRigidBody
59public class BulletBody
60{
61 public BulletBody(uint id)
62 {
63 ID = id;
64 collisionType = CollisionType.Static;
65 }
66 public uint ID;
67 public CollisionType collisionType;
68
69 public virtual void Clear() { }
70 public virtual bool HasPhysicalBody { get { return false; } }
71
72 // Apply the specificed collision mask into the physical world
73 public virtual bool ApplyCollisionMask(BSScene physicsScene)
74 {
75 // Should assert the body has been added to the physical world.
76 // (The collision masks are stored in the collision proxy cache which only exists for
77 // a collision body that is in the world.)
78 return physicsScene.PE.SetCollisionGroupMask(this,
79 BulletSimData.CollisionTypeMasks[collisionType].group,
80 BulletSimData.CollisionTypeMasks[collisionType].mask);
81 }
82
83 // Used for log messages for a unique display of the memory/object allocated to this instance
84 public virtual string AddrString
85 {
86 get { return "unknown"; }
87 }
88
89 public override string ToString()
90 {
91 StringBuilder buff = new StringBuilder();
92 buff.Append("<id=");
93 buff.Append(ID.ToString());
94 buff.Append(",p=");
95 buff.Append(AddrString);
96 buff.Append(",c=");
97 buff.Append(collisionType);
98 buff.Append(">");
99 return buff.ToString();
100 }
101}
102
103public class BulletShape
104{
105 public BulletShape()
106 {
107 type = BSPhysicsShapeType.SHAPE_UNKNOWN;
108 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
109 isNativeShape = false;
110 }
111 public BSPhysicsShapeType type;
112 public System.UInt64 shapeKey;
113 public bool isNativeShape;
114
115 public virtual void Clear() { }
116 public virtual bool HasPhysicalShape { get { return false; } }
117
118 // Make another reference to this physical object.
119 public virtual BulletShape Clone() { return new BulletShape(); }
120
121 // Return 'true' if this and other refer to the same physical object
122 public virtual bool ReferenceSame(BulletShape xx) { return false; }
123
124 // Used for log messages for a unique display of the memory/object allocated to this instance
125 public virtual string AddrString
126 {
127 get { return "unknown"; }
128 }
129
130 public override string ToString()
131 {
132 StringBuilder buff = new StringBuilder();
133 buff.Append("<p=");
134 buff.Append(AddrString);
135 buff.Append(",s=");
136 buff.Append(type.ToString());
137 buff.Append(",k=");
138 buff.Append(shapeKey.ToString("X"));
139 buff.Append(",n=");
140 buff.Append(isNativeShape.ToString());
141 buff.Append(">");
142 return buff.ToString();
143 }
144}
145
146// An allocated Bullet btConstraint
147public class BulletConstraint
148{
149 public BulletConstraint()
150 {
151 }
152 public virtual void Clear() { }
153 public virtual bool HasPhysicalConstraint { get { return false; } }
154
155 // Used for log messages for a unique display of the memory/object allocated to this instance
156 public virtual string AddrString
157 {
158 get { return "unknown"; }
159 }
160}
161
162// An allocated HeightMapThing which holds various heightmap info.
163// Made a class rather than a struct so there would be only one
164// instance of this and C# will pass around pointers rather
165// than making copies.
166public class BulletHMapInfo
167{
168 public BulletHMapInfo(uint id, float[] hm) {
169 ID = id;
170 heightMap = hm;
171 terrainRegionBase = OMV.Vector3.Zero;
172 minCoords = new OMV.Vector3(100f, 100f, 25f);
173 maxCoords = new OMV.Vector3(101f, 101f, 26f);
174 minZ = maxZ = 0f;
175 sizeX = sizeY = 256f;
176 }
177 public uint ID;
178 public float[] heightMap;
179 public OMV.Vector3 terrainRegionBase;
180 public OMV.Vector3 minCoords;
181 public OMV.Vector3 maxCoords;
182 public float sizeX, sizeY;
183 public float minZ, maxZ;
184 public BulletShape terrainShape;
185 public BulletBody terrainBody;
186}
187
188// The general class of collsion object.
189public enum CollisionType
190{
191 Avatar,
192 Groundplane,
193 Terrain,
194 Static,
195 Dynamic,
196 VolumeDetect,
197 // Linkset, // A linkset should be either Static or Dynamic
198 LinksetChild,
199 Unknown
200};
201
202// Hold specification of group and mask collision flags for a CollisionType
203public struct CollisionTypeFilterGroup
204{
205 public CollisionTypeFilterGroup(CollisionType t, uint g, uint m)
206 {
207 type = t;
208 group = g;
209 mask = m;
210 }
211 public CollisionType type;
212 public uint group;
213 public uint mask;
214};
215
216public static class BulletSimData
217{
218
219// Map of collisionTypes to flags for collision groups and masks.
220// An object's 'group' is the collison groups this object belongs to
221// An object's 'filter' is the groups another object has to belong to in order to collide with me
222// A collision happens if ((obj1.group & obj2.filter) != 0) || ((obj2.group & obj1.filter) != 0)
223//
224// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code
225// but, instead, use references to this dictionary. Finding and debugging
226// collision flag problems will be made easier.
227public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks
228 = new Dictionary<CollisionType, CollisionTypeFilterGroup>()
229{
230 { CollisionType.Avatar,
231 new CollisionTypeFilterGroup(CollisionType.Avatar,
232 (uint)CollisionFilterGroups.BCharacterGroup,
233 (uint)CollisionFilterGroups.BAllGroup)
234 },
235 { CollisionType.Groundplane,
236 new CollisionTypeFilterGroup(CollisionType.Groundplane,
237 (uint)CollisionFilterGroups.BGroundPlaneGroup,
238 (uint)CollisionFilterGroups.BAllGroup)
239 },
240 { CollisionType.Terrain,
241 new CollisionTypeFilterGroup(CollisionType.Terrain,
242 (uint)CollisionFilterGroups.BTerrainGroup,
243 (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup))
244 },
245 { CollisionType.Static,
246 new CollisionTypeFilterGroup(CollisionType.Static,
247 (uint)CollisionFilterGroups.BStaticGroup,
248 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
249 },
250 { CollisionType.Dynamic,
251 new CollisionTypeFilterGroup(CollisionType.Dynamic,
252 (uint)CollisionFilterGroups.BSolidGroup,
253 (uint)(CollisionFilterGroups.BAllGroup))
254 },
255 { CollisionType.VolumeDetect,
256 new CollisionTypeFilterGroup(CollisionType.VolumeDetect,
257 (uint)CollisionFilterGroups.BSensorTrigger,
258 (uint)(~CollisionFilterGroups.BSensorTrigger))
259 },
260 { CollisionType.LinksetChild,
261 new CollisionTypeFilterGroup(CollisionType.LinksetChild,
262 (uint)CollisionFilterGroups.BLinksetChildGroup,
263 (uint)(CollisionFilterGroups.BNoneGroup))
264 // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
265 },
266};
267
268}
269}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
new file mode 100755
index 0000000..bda7c47
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -0,0 +1,335 @@
1CURRENT PRIORITIES
2=================================================
3One sided meshes? Should terrain be built into a closed shape?
4 When meshes get partially wedged into the terrain, they cannot push themselves out.
5 It is possible that Bullet processes collisions whether entering or leaving a mesh.
6 Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869
7Deleting a linkset while standing on the root will leave the physical shape of the root behind.
8 Not sure if it is because standing on it. Done with large prim linksets.
9Terrain detail: double terrain mesh detail
10Vehicle angular vertical attraction
11vehicle angular banking
12Center-of-gravity
13Vehicle angular deflection
14 Preferred orientation angular correction fix
15when should angular and linear motor targets be zeroed? when selected?
16 Need a vehicle.clear()? Or an 'else' in prestep if not physical.
17Teravus llMoveToTarget script debug
18 Mixing of hover, buoyancy/gravity, moveToTarget, into one force
19 Setting hover height to zero disables hover even if hover flags are on (from SL wiki)
20Nebadon vehicles turning funny in arena
21limitMotorUp calibration (more down?)
22llRotLookAt
23llLookAt
24Avatars walking up stairs (HALF DONE)
25Avatar movement
26 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
27 walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
28 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
29Enable vehicle border crossings (at least as poorly as ODE)
30 Terrain skirts
31 Avatar created in previous region and not new region when crossing border
32 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
33Vehicle script tuning/debugging
34 Avanti speed script
35 Weapon shooter script
36Add material densities to the material types
37
38VEHICLES TODO LIST:
39=================================================
40Border crossing with linked vehicle causes crash
41 20121129.1411: editting/moving phys object across region boundries causes crash
42 getPos-> btRigidBody::upcast -> getBodyType -> BOOM
43Vehicles (Move smoothly)
44Some vehicles should not be able to turn if no speed or off ground.
45What to do if vehicle and prim buoyancy differ?
46Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
47Neb car jiggling left and right
48 Happens on terrain and any other mesh object. Flat cubes are much smoother.
49 This has been reduced but not eliminated.
50Implement referenceFrame for all the motion routines.
51For limitMotorUp, use raycast down to find if vehicle is in the air.
52Verify llGetVel() is returning a smooth and good value for vehicle movement.
53llGetVel() should return the root's velocity if requested in a child prim.
54Implement function efficiency for lineaar and angular motion.
55After getting off a vehicle, the root prim is phantom (can be walked through)
56 Need to force a position update for the root prim after compound shape destruction
57Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
58Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties().
59 A kludge that isn't fixing the real problem of Bullet adding extra motion.
60Incorporate inter-relationship of angular corrections. For instance, angularDeflection
61 and angularMotorUp will compute same X or Y correction. When added together
62 creates over-correction and over-shoot and wabbling.
63Vehicle attributes are not restored when a vehicle is rezzed on region creation
64 Create vehicle, setup vehicle properties, restart region, vehicle is not reinitialized.
65
66GENERAL TODO LIST:
67=================================================
68Level-of-detail for mesh creation. Prims with circular interiors require lod of 32.
69 Is much saved with lower LODs? At the moment, all set to 32.
70Collisions are inconsistant: arrows are supposed to hit and report collision. Often don't.
71 If arrow show at prim, collision reported about 1/3 of time. If collision reported,
72 both arrow and prim report it. The arrow bounces off the prim 9 out of 10 times.
73 Shooting 5m sphere "arrows" at 60m/s.
74llMoveToTarget objects are not effected by gravity until target is removed.
75Compute CCD parameters based on body size
76Can solver iterations be changed per body/shape? Can be for constraints but what
77 about regular vehicles?
78Implement llSetPhysicalMaterial.
79 extend it with Center-of-mass, rolling friction, density
80Implement llSetForceAndTorque.
81Change BSPrim.moveToTarget to used forces rather than changing position
82 Changing position allows one to move through walls
83Implement an avatar mesh shape. The Bullet capsule is way too limited.
84 Consider just hand creating a vertex/index array in a new BSShapeAvatar.
85Verify/fix phantom, volume-detect objects do not fall to infinity. Should stop at terrain.
86Revisit CollisionMargin. Builders notice the 0.04 spacing between prims.
87Duplicating a physical prim causes old prim to jump away
88 Dup a phys prim and the original become unselected and thus interacts w/ selected prim.
89Scenes with hundred of thousands of static objects take a lot of physics CPU time.
90BSPrim.Force should set a continious force on the prim. The force should be
91 applied each tick. Some limits?
92Gun sending shooter flying.
93Collision margin (gap between physical objects lying on each other)
94Boundry checking (crashes related to crossing boundry)
95 Add check for border edge position for avatars and objects.
96 Verify the events are created for border crossings.
97Avatar rotation (check out changes to ScenePresence for physical rotation)
98Avatar running (what does phys engine need to do?)
99Small physical objects do not interact correctly
100 Create chain of .5x.5x.1 torui and make all but top physical so to hang.
101 The chain will fall apart and pairs will dance around on ground
102 Chains of 1x1x.2 will stay connected but will dance.
103 Chains above 2x2x.4 are more stable and get stablier as torui get larger.
104Add PID motor for avatar movement (slow to stop, ...)
105setForce should set a constant force. Different than AddImpulse.
106Implement raycast.
107Implement ShapeCollection.Dispose()
108Implement water as a plain so raycasting and collisions can happen with same.
109Add collision penetration return
110 Add field passed back by BulletSim.dll and fill with info in ManifoldConstact.GetDistance()
111Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
112 Also osGetPhysicsEngineVerion() maybe.
113Linkset.Position and Linkset.Orientation requre rewrite to properly return
114 child position. LinksetConstraint acts like it's at taint time!!
115Implement LockAngularMotion -- implements llSetStatus(ROTATE_AXIS_*, T/F)
116Should the different PID factors have non-equal contributions for different
117 values of Efficiency?
118Selecting and deselecting physical objects causes CPU processing time to jump
119 http://www.youtube.com/watch?v=Hjg57fWg8yI&hd=1
120 put thousand physical objects, select and deselect same. CPU time will be large.
121Re-implement buoyancy as a separate force on the object rather than diddling gravity.
122 Register a pre-step event to add the force.
123More efficient memory usage when passing hull information from BSPrim to BulletSim
124Avatar movement motor check for zero or small movement. Somehow suppress small movements
125 when avatar has stopped and is just standing. Simple test for near zero has
126 the problem of preventing starting up (increase from zero) especially when falling.
127Physical and phantom will drop through the terrain
128
129
130LINKSETS
131======================================================
132Child prims do not report collisions
133Allow children of a linkset to be phantom:
134 http://opensim-dev.2196679.n2.nabble.com/Setting-a-single-child-prim-to-Phantom-tp7578513.html
135 Add OS_STATUS_PHANTOM_PRIM to llSetLinkPrimitaveParamsFast.
136Editing a child of a linkset causes the child to go phantom
137 Move a child prim once when it is physical and can never move it again without it going phantom
138Offset the center of the linkset to be the geometric center of all the prims
139 Not quite the same as the center-of-gravity
140Linksets should allow collisions to individual children
141 Add LocalID to children shapes in LinksetCompound and create events for individuals
142LinksetCompound: when one of the children changes orientation (like tires
143 turning on a vehicle, the whole compound object is rebuilt. Optimize this
144 so orientation/position of individual children can change without a rebuild.
145Verify/think through scripts in children of linksets. What do they reference
146 and return when getting position, velocity, ...
147Confirm constraint linksets still work after making all the changes for compound linksets.
148Use PostTaint callback to do rebuilds for constraint linksets to reduce rebuilding
149Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt.
150 For compound linksets, add ability to remove or reposition individual child shapes.
151Speed up creation of large physical linksets
152 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical.
153 REALLY bad for very large physical linksets (freezes the sim for many seconds).
154Eliminate collisions between objects in a linkset. (LinksetConstraint)
155 Have UserPointer point to struct with localID and linksetID?
156 Objects in original linkset still collide with each other?
157
158MORE
159======================================================
160Create tests for different interface components
161 Have test objects/scripts measure themselves and turn color if correct/bad
162 Test functions in SL and calibrate correctness there
163 Create auto rezzer and tracker to run through the tests
164Use the HACD convex hull routine in Bullet rather than the C# version.
165Do we need to do convex hulls all the time? Can complex meshes be left meshes?
166 There is some problem with meshes and collisions
167 Hulls are not as detailed as meshes. Hulled vehicles insides are different shape.
168Debounce avatar contact so legs don't keep folding up when standing.
169Implement LSL physics controls. Like STATUS_ROTATE_X.
170Add border extensions to terrain to help region crossings and objects leaving region.
171Use a different capsule shape for avatar when sitting
172 LL uses a pyrimidal shape scaled by the avatar's bounding box
173 http://wiki.secondlife.com/wiki/File:Avmeshforms.png
174Performance test with lots of avatars. Can BulletSim support a thousand?
175Optimize collisions in C++: only send up to the object subscribed to collisions.
176 Use collision subscription and remove the collsion(A,B) and collision(B,A)
177Check whether SimMotionState needs large if statement (see TODO).
178Implement 'top colliders' info.
179Avatar jump
180Performance measurement and changes to make quicker.
181Implement detailed physics stats (GetStats()).
182Measure performance improvement from hulls
183Test not using ghost objects for volume detect implementation.
184Performance of closures and delegates for taint processing
185 Are there faster ways?
186 Is any slowdown introduced by the existing implementation significant?
187Is there are more efficient method of implementing pre and post step actions?
188 See http://www.codeproject.com/Articles/29922/Weak-Events-in-C
189Physics Arena central pyramid: why is one side permiable?
190In SL, perfect spheres don't seem to have rolling friction. Add special case.
191Enforce physical parameter min/max:
192 Gravity: [-1, 28]
193 Friction: [0, 255]
194 Density: [1, 22587]
195 Restitution [0, 1]
196 http://wiki.secondlife.com/wiki/Physics_Material_Settings_test
197Avatar attachments have no mass? http://forums-archive.secondlife.com/54/f0/31796/1.html
198Keep avatar scaling correct. http://pennycow.blogspot.fr/2011/07/matter-of-scale.html
199
200INTERNAL IMPROVEMENT/CLEANUP
201=================================================
202Can the 'inTaintTime' flag be cleaned up and used? For instance, a call to
203 BSScene.TaintedObject() could immediately execute the callback if already in taint time.
204Create the physical wrapper classes (BulletBody, BulletShape) by methods on
205 BSAPITemplate and make their actual implementation Bullet engine specific.
206 For the short term, just call the existing functions in ShapeCollection.
207Consider moving prim/character body and shape destruction in destroy()
208 to postTimeTime rather than protecting all the potential sets that
209 might have been queued up.
210Remove unused fields from ShapeData (not used in API2)
211Remove unused fields from pinned memory shared parameter block
212 Create parameter variables in BSScene to replace same.
213Breakout code for mesh/hull/compound/native into separate BSShape* classes
214 Standardize access to building and reference code.
215 The skeleton classes are in the sources but are not complete or linked in.
216Make BSBody and BSShape real classes to centralize creation/changin/destruction
217 Convert state and parameter calls from BulletSimAPI direct calls to
218 calls on BSBody and BSShape
219Generalize Dynamics and PID with standardized motors.
220Generalize Linkset and vehicles into PropertyManagers
221 Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
222 Potentially add events for shape destruction, etc.
223Better mechanism for resetting linkset set and vehicle parameters when body rebuilt.
224 BSPrim.CreateGeomAndObject is kludgy with the callbacks, etc.
225Implement linkset by setting position of children when root updated. (LinksetManual)
226 Linkset implementation using manual prim movement.
227LinkablePrim class? Would that simplify/centralize the linkset logic?
228BSScene.UpdateParameterSet() is broken. How to set params on objects?
229Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
230 bob at the water level. BSPrim.PositionSanityCheck()
231Should taints check for existance or activeness of target?
232 When destroying linksets/etc, taints can be generated for objects that are
233 actually gone when the taint happens. Crashes don't happen because the taint closure
234 keeps the object from being freed, but that is just an accident.
235 Possibly have an 'active' flag that is checked by the taint processor?
236Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones)
237Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'?
238There are TOO MANY interfaces from BulletSim core to Bullet itself
239 Think of something to eliminate one or more of the layers
240
241THREADING
242=================================================
243Do taint action immediately if not actually executing Bullet.
244 Add lock around Bullet execution and just do taint actions if simulation is not happening.
245
246DONE DONE DONE DONE
247=================================================
248Cleanup code in BSDynamics by using motors. (Resolution: started)
249Consider implementing terrain with a mesh rather than heightmap. (Resolution: done)
250 Would have better and adjustable resolution.
251Build terrain mesh so heighmap is height of the center of the square meter.
252 Resolution: NOT DONE: SL and ODE define meter square as being at one corner with one diagional.
253Terrain as mesh. (Resolution: done)
254How are static linksets seen by the physics engine?
255 Resolution: they are not linked in physics. When moved, all the children are repositioned.
256Convert BSCharacter to use all API2 (Resolution: done)
257Avatar pushing difficult (too heavy?)
258Use asset service passed to BulletSim to get sculptie bodies, etc. (Resolution: done)
259Remove old code in DLL (all non-API2 stuff). (Resolution: done)
260Measurements of mega-physical prim performance (with graph) (Resolution: done, email)
261Debug Bullet internal stats output (why is timing all wrong?)
262 Resolution: Bullet stats logging only works with a single instance of Bullet (one region).
263Implement meshes or just verify that they work. (Resolution: they do!)
264Do prim hash codes work for sculpties and meshes? (Resolution: yes)
265Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound)
266 Compound shapes will need the LocalID in the shapes and collision
267 processing to get it from there.
268Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.)
269Package Bullet source mods for Bullet internal stats output
270 (Resolution: move code into WorldData.h rather than relying on patches)
271Single prim vehicles don't seem to properly vehiclize.
272 (Resolution: mass was not getting set properly for single prim linksets)
273Add material type linkage and input all the material property definitions.
274 Skeleton classes and table are in the sources but are not filled or used.
275 (Resolution:
276Neb vehicle taking > 25ms of physics time!!
277 (Resolution: compound linksets were being rebuild WAY too often)
278Avatar height off after unsitting (floats off ground)
279 Editting appearance then moving restores.
280 Must not be initializing height when recreating capsule after unsit.
281 (Resolution: confusion of scale vs size for native objects removed)
282Light cycle falling over when driving (Resolution: implemented angularMotorUp)
283Should vehicle angular/linear movement friction happen after all the components
284 or does it only apply to the basic movement?
285 (Resolution: friction added before returning newly computed motor value.
286 What is expected by some vehicles (turning up friction to moderate speed))
287Tune terrain/object friction to be closer to SL.
288 (Resolution: added material type with friction and resolution)
289Smooth avatar movement with motor (DONE)
290 Should motor update be all at taint-time? (Yes, DONE)
291 Fix avatar slowly sliding when standing (zero motion when stopped) (DONE)
292 (Resolution: added BSVMotor for avatar starting and stopping)
293llApplyImpulse()
294 Compare mass/movement in OS and SL. Calibrate actions. (DONE)
295 (Resolution: tested on SL and OS. AddForce scales the force for timestep)
296llSetBuoyancy() (DONE)
297 (Resolution: Bullet resets object gravity when added to world. Moved set gravity)
298Avatar density is WAY off. Compare and calibrate with what's in SL. (DONE)
299 (Resolution: set default density to 3.5 (from 60) which is closer to SL)
300Redo BulletSimAPI to allow native C# implementation of Bullet option (DONE)
301 (Resolution: added BSAPITemplate and then interfaces for C++ Bullet and C# BulletXNA
302Meshes rendering as bounding boxes (DONE)
303 (Resolution: Added test for mesh/sculpties in native shapes so it didn't think it was a box)
304llMoveToTarget (Resolution: added simple motor to update the position.)
305Angular motor direction is global coordinates rather than local coordinates (DONE)
306Add vehicle collisions so IsColliding is properly reported. (DONE)
307 Needed for banking, limitMotorUp, movementLimiting, ...
308 (Resolution: added CollisionFlags.BS_VEHICLE_COLLISION and code to use it)
309VehicleAddForce is not scaled by the simulation step but it is only
310 applied for one step. Should it be scaled? (DONE)
311 (Resolution: use force for timed things, Impulse for immediate, non-timed things)
312Complete implemention of preStepActions (DONE)
313 Replace vehicle step call with prestep event.
314 Is there a need for postStepActions? postStepTaints?
315Disable activity of passive linkset children. (DONE)
316 Since the linkset is a compound object, the old prims are left lying
317 around and need to be phantomized so they don't collide, ...
318Remove HeightmapInfo from terrain specification (DONE)
319 Since C++ code does not need terrain height, this structure et al are not needed.
320Surfboard go wonky when turning (DONE)
321 Angular motor direction is global coordinates rather than local coordinates?
322 (Resolution: made angular motor direction correct coordinate system)
323Mantis 6040 script http://opensimulator.org/mantis/view.php?id=6040 (DONE)
324 Msg Kayaker on OSGrid when working
325 (Resolution: LINEAR_DIRECTION is in vehicle coords. Test script does the
326 same in SL as in OS/BulletSim)
327Boats float low in the water (DONE)
328Boats floating at proper level (DONE)
329When is force introduced by SetForce removed? The prestep action could go forever. (DONE)
330 (Resolution: setForce registers a prestep action which keeps applying the force)
331Child movement in linkset (don't rebuild linkset) (DONE 20130122))
332Avatar standing on a moving object should start to move with the object. (DONE 20130125)
333Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
334 Verify that angular motion specified around Z moves in the vehicle coordinates.
335 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates. \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
index 0d1db3b..d240c71 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs b/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs
new file mode 100755
index 0000000..33232bd
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs
@@ -0,0 +1,150 @@
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;
32
33using NUnit.Framework;
34using log4net;
35
36using OpenSim.Framework;
37using OpenSim.Region.Physics.BulletSPlugin;
38using OpenSim.Region.Physics.Manager;
39using OpenSim.Tests.Common;
40
41using OpenMetaverse;
42
43namespace OpenSim.Region.Physics.BulletSPlugin.Tests
44{
45[TestFixture]
46public class BasicVehicles : OpenSimTestCase
47{
48 // Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1
49 // Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1
50
51 BSScene PhysicsScene { get; set; }
52 BSPrim TestVehicle { get; set; }
53 Vector3 TestVehicleInitPosition { get; set; }
54 float simulationTimeStep = 0.089f;
55
56 [TestFixtureSetUp]
57 public void Init()
58 {
59 Dictionary<string, string> engineParams = new Dictionary<string, string>();
60 PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams);
61
62 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere();
63 Vector3 pos = new Vector3(100.0f, 100.0f, 0f);
64 pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2f;
65 TestVehicleInitPosition = pos;
66 Vector3 size = new Vector3(1f, 1f, 1f);
67 pbs.Scale = size;
68 Quaternion rot = Quaternion.Identity;
69 bool isPhys = false;
70 uint localID = 123;
71
72 PhysicsScene.AddPrimShape("testPrim", pbs, pos, size, rot, isPhys, localID);
73 TestVehicle = (BSPrim)PhysicsScene.PhysObjects[localID];
74 // The actual prim shape creation happens at taint time
75 PhysicsScene.ProcessTaints();
76
77 }
78
79 [TestFixtureTearDown]
80 public void TearDown()
81 {
82 if (PhysicsScene != null)
83 {
84 // The Dispose() will also free any physical objects in the scene
85 PhysicsScene.Dispose();
86 PhysicsScene = null;
87 }
88 }
89
90 [TestCase(2f, 0.2f, 0.25f, 0.25f, 0.25f)]
91 [TestCase(2f, 0.2f, -0.25f, 0.25f, 0.25f)]
92 [TestCase(2f, 0.2f, 0.25f, -0.25f, 0.25f)]
93 [TestCase(2f, 0.2f, -0.25f, -0.25f, 0.25f)]
94 // [TestCase(2f, 0.2f, 0.785f, 0.0f, 0.25f) /*, "Leaning 45 degrees to the side" */]
95 // [TestCase(2f, 0.2f, 1.650f, 0.0f, 0.25f) /*, "Leaning more than 90 degrees to the side" */]
96 // [TestCase(2f, 0.2f, 2.750f, 0.0f, 0.25f) /*, "Almost upside down, tipped right" */]
97 // [TestCase(2f, 0.2f,-2.750f, 0.0f, 0.25f) /*, "Almost upside down, tipped left" */]
98 // [TestCase(2f, 0.2f, 0.0f, 0.785f, 0.25f) /*, "Tipped back 45 degrees" */]
99 // [TestCase(2f, 0.2f, 0.0f, 1.650f, 0.25f) /*, "Tipped back more than 90 degrees" */]
100 // [TestCase(2f, 0.2f, 0.0f, 2.750f, 0.25f) /*, "Almost upside down, tipped back" */]
101 // [TestCase(2f, 0.2f, 0.0f,-2.750f, 0.25f) /*, "Almost upside down, tipped forward" */]
102 public void AngularVerticalAttraction(float timeScale, float efficiency, float initRoll, float initPitch, float initYaw)
103 {
104 // Enough simulation steps to cover the timescale the operation should take
105 int simSteps = (int)(timeScale / simulationTimeStep) + 1;
106
107 // Tip the vehicle
108 Quaternion initOrientation = Quaternion.CreateFromEulers(initRoll, initPitch, initYaw);
109 TestVehicle.Orientation = initOrientation;
110
111 TestVehicle.Position = TestVehicleInitPosition;
112
113 // The vehicle controller is not enabled directly (by setting a vehicle type).
114 // Instead the appropriate values are set and calls are made just the parts of the
115 // controller we want to exercise. Stepping the physics engine then applies
116 // the actions of that one feature.
117 TestVehicle.VehicleController.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency);
118 TestVehicle.VehicleController.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, timeScale);
119 TestVehicle.VehicleController.enableAngularVerticalAttraction = true;
120
121 TestVehicle.IsPhysical = true;
122 PhysicsScene.ProcessTaints();
123
124 // Step the simulator a bunch of times and vertical attraction should orient the vehicle up
125 for (int ii = 0; ii < simSteps; ii++)
126 {
127 TestVehicle.VehicleController.ForgetKnownVehicleProperties();
128 TestVehicle.VehicleController.ComputeAngularVerticalAttraction();
129 TestVehicle.VehicleController.PushKnownChanged();
130
131 PhysicsScene.Simulate(simulationTimeStep);
132 }
133
134 TestVehicle.IsPhysical = false;
135 PhysicsScene.ProcessTaints();
136
137 // After these steps, the vehicle should be upright
138 /*
139 float finalRoll, finalPitch, finalYaw;
140 TestVehicle.Orientation.GetEulerAngles(out finalRoll, out finalPitch, out finalYaw);
141 Assert.That(finalRoll, Is.InRange(-0.01f, 0.01f));
142 Assert.That(finalPitch, Is.InRange(-0.01f, 0.01f));
143 Assert.That(finalYaw, Is.InRange(initYaw - 0.1f, initYaw + 0.1f));
144 */
145
146 Vector3 upPointer = Vector3.UnitZ * TestVehicle.Orientation;
147 Assert.That(upPointer.Z, Is.GreaterThan(0.99f));
148 }
149}
150} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Tests/BulletSimTests.cs b/OpenSim/Region/Physics/BulletSPlugin/Tests/BulletSimTests.cs
new file mode 100755
index 0000000..35cbc1d
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/Tests/BulletSimTests.cs
@@ -0,0 +1,56 @@
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;
32
33using NUnit.Framework;
34using log4net;
35
36using OpenSim.Tests.Common;
37
38namespace OpenSim.Region.Physics.BulletSPlugin.Tests
39{
40[TestFixture]
41public class BulletSimTests : OpenSimTestCase
42{
43 // Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1
44 // Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1
45
46 [TestFixtureSetUp]
47 public void Init()
48 {
49 }
50
51 [TestFixtureTearDown]
52 public void TearDown()
53 {
54 }
55}
56}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Tests/BulletSimTestsUtil.cs b/OpenSim/Region/Physics/BulletSPlugin/Tests/BulletSimTestsUtil.cs
new file mode 100755
index 0000000..28207a4
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/Tests/BulletSimTestsUtil.cs
@@ -0,0 +1,95 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Collections.Generic;
31using System.Linq;
32using System.Text;
33
34using Nini.Config;
35
36using OpenSim.Framework;
37using OpenSim.Region.Physics.BulletSPlugin;
38using OpenSim.Region.Physics.Meshing;
39
40namespace OpenSim.Region.Physics.BulletSPlugin.Tests
41{
42// Utility functions for building up and tearing down the sample physics environments
43public static class BulletSimTestsUtil
44{
45 // 'engineName' is the Bullet engine to use. Either null (for unmanaged), "BulletUnmanaged" or "BulletXNA"
46 // 'params' is a set of keyValue pairs to set in the engine's configuration file (override defaults)
47 // May be 'null' if there are no overrides.
48 public static BSScene CreateBasicPhysicsEngine(Dictionary<string,string> paramOverrides)
49 {
50 IConfigSource openSimINI = new IniConfigSource();
51 IConfig startupConfig = openSimINI.AddConfig("Startup");
52 startupConfig.Set("physics", "BulletSim");
53 startupConfig.Set("meshing", "Meshmerizer");
54 startupConfig.Set("cacheSculptMaps", "false"); // meshmerizer shouldn't save maps
55
56 IConfig bulletSimConfig = openSimINI.AddConfig("BulletSim");
57 // If the caller cares, specify the bullet engine otherwise it will default to "BulletUnmanaged".
58 // bulletSimConfig.Set("BulletEngine", "BulletUnmanaged");
59 // bulletSimConfig.Set("BulletEngine", "BulletXNA");
60 bulletSimConfig.Set("MeshSculptedPrim", "false");
61 bulletSimConfig.Set("ForceSimplePrimMeshing", "true");
62 if (paramOverrides != null)
63 {
64 foreach (KeyValuePair<string, string> kvp in paramOverrides)
65 {
66 bulletSimConfig.Set(kvp.Key, kvp.Value);
67 }
68 }
69
70 // If a special directory exists, put detailed logging therein.
71 // This allows local testing/debugging without having to worry that the build engine will output logs.
72 if (Directory.Exists("physlogs"))
73 {
74 bulletSimConfig.Set("PhysicsLoggingDir","./physlogs");
75 bulletSimConfig.Set("PhysicsLoggingEnabled","True");
76 bulletSimConfig.Set("PhysicsLoggingDoFlush","True");
77 bulletSimConfig.Set("VehicleLoggingEnabled","True");
78 }
79
80 BSPlugin bsPlugin = new BSPlugin();
81
82 BSScene bsScene = (BSScene)bsPlugin.GetScene("BSTestRegion");
83
84 // Since the asset requestor is not initialized, any mesh or sculptie will be a cube.
85 // In the future, add a fake asset fetcher to get meshes and sculpts.
86 // bsScene.RequestAssetMethod = ???;
87
88 Meshing.Meshmerizer mesher = new Meshmerizer(openSimINI);
89 bsScene.Initialise(mesher, openSimINI);
90
91 return bsScene;
92 }
93
94}
95}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
index 8de70ef..ba24aa7 100644
--- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
@@ -2190,7 +2190,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2190 convex = false; 2190 convex = false;
2191 try 2191 try
2192 { 2192 {
2193 _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, (int)LevelOfDetail.High, true,convex,false); 2193 _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, (int)LevelOfDetail.High, true,false,convex,false);
2194 } 2194 }
2195 catch 2195 catch
2196 { 2196 {
@@ -2557,7 +2557,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2557 2557
2558 try 2558 try
2559 { 2559 {
2560 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true, convex,false); 2560 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true, false,convex,false);
2561 } 2561 }
2562 catch 2562 catch
2563 { 2563 {
diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
index 5ff945d..cafd7f4 100644
--- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
32// You can specify all the values or you can default the Build and Revision Numbers 32// You can specify all the values or you can default the Build and Revision Numbers
33// by using the '*' as shown below: 33// by using the '*' as shown below:
34// [assembly: AssemblyVersion("1.0.*")] 34// [assembly: AssemblyVersion("1.0.*")]
35[assembly: AssemblyVersion("0.7.5.*")] 35[assembly: AssemblyVersion("0.7.6.*")]
36[assembly: AssemblyFileVersion("1.0.0.0")] 36[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
index 36b4235..5da3956 100644
--- a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.5.*")] 58[assembly : AssemblyVersion("0.7.6.*")]
diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs
index ecc2918..5485eb7 100644
--- a/OpenSim/Region/Physics/Manager/IMesher.cs
+++ b/OpenSim/Region/Physics/Manager/IMesher.cs
@@ -37,7 +37,7 @@ namespace OpenSim.Region.Physics.Manager
37 { 37 {
38 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); 38 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod);
39 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); 39 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical);
40 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde); 40 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde);
41 IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex); 41 IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex);
42 void ReleaseMesh(IMesh mesh); 42 void ReleaseMesh(IMesh mesh);
43 void ExpireReleaseMeshs(); 43 void ExpireReleaseMeshs();
@@ -83,6 +83,7 @@ namespace OpenSim.Region.Physics.Manager
83 List<Vector3> getVertexList(); 83 List<Vector3> getVertexList();
84 int[] getIndexListAsInt(); 84 int[] getIndexListAsInt();
85 int[] getIndexListAsIntLocked(); 85 int[] getIndexListAsIntLocked();
86 float[] getVertexListAsFloat();
86 float[] getVertexListAsFloatLocked(); 87 float[] getVertexListAsFloatLocked();
87 void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount); 88 void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount);
88 void getVertexListAsPtrToFloatArray(out IntPtr vertexList, out int vertexStride, out int vertexCount); 89 void getVertexListAsPtrToFloatArray(out IntPtr vertexList, out int vertexStride, out int vertexCount);
diff --git a/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs b/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs
index b8676ba..31a397c 100755
--- a/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs
+++ b/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs
@@ -60,14 +60,14 @@ namespace OpenSim.Region.Physics.Manager
60 60
61 // Set parameter on a specific or all instances. 61 // Set parameter on a specific or all instances.
62 // Return 'false' if not able to set the parameter. 62 // Return 'false' if not able to set the parameter.
63 bool SetPhysicsParameter(string parm, float value, uint localID); 63 bool SetPhysicsParameter(string parm, string value, uint localID);
64 64
65 // Get parameter. 65 // Get parameter.
66 // Return 'false' if not able to get the parameter. 66 // Return 'false' if not able to get the parameter.
67 bool GetPhysicsParameter(string parm, out float value); 67 bool GetPhysicsParameter(string parm, out string value);
68 68
69 // Get parameter from a particular object 69 // Get parameter from a particular object
70 // TODO: 70 // TODO:
71 // bool GetPhysicsParameter(string parm, out float value, uint localID); 71 // bool GetPhysicsParameter(string parm, out string value, uint localID);
72 } 72 }
73} 73}
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 9338130..e2789d6 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -349,17 +349,20 @@ namespace OpenSim.Region.Physics.Manager
349 } 349 }
350 350
351 /// <summary> 351 /// <summary>
352 /// Velocity of this actor. 352 /// The desired velocity of this actor.
353 /// </summary> 353 /// </summary>
354 /// <remarks> 354 /// <remarks>
355 /// Setting this provides a target velocity for physics scene updates. 355 /// Setting this provides a target velocity for physics scene updates.
356 /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity, 356 /// Getting this returns the last set target. Fetch Velocity to get the current velocity.
357 /// time to accelerate and collisions.
358 /// </remarks> 357 /// </remarks>
358 protected Vector3 m_targetVelocity;
359 public virtual Vector3 TargetVelocity 359 public virtual Vector3 TargetVelocity
360 { 360 {
361 get { return Velocity; } 361 get { return m_targetVelocity; }
362 set { Velocity = value; } 362 set {
363 m_targetVelocity = value;
364 Velocity = m_targetVelocity;
365 }
363 } 366 }
364 367
365 public abstract Vector3 Velocity { get; set; } 368 public abstract Vector3 Velocity { get; set; }
diff --git a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
index 8587a2b..8ccfda5 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
@@ -30,7 +30,7 @@ using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Reflection; 31using System.Reflection;
32using Nini.Config; 32using Nini.Config;
33using log4net; 33using log4net;
34using OpenSim.Framework; 34using OpenSim.Framework;
35 35
36namespace OpenSim.Region.Physics.Manager 36namespace OpenSim.Region.Physics.Manager
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index 57e2d20..20a70b4 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.Physics.Manager
47 public delegate void JointDeactivated(PhysicsJoint joint); 47 public delegate void JointDeactivated(PhysicsJoint joint);
48 public delegate void JointErrorMessage(PhysicsJoint joint, string message); // this refers to an "error message due to a problem", not "amount of joint constraint violation" 48 public delegate void JointErrorMessage(PhysicsJoint joint, string message); // this refers to an "error message due to a problem", not "amount of joint constraint violation"
49 49
50 public enum RayFilterFlags:ushort 50 public enum RayFilterFlags : ushort
51 { 51 {
52 // the flags 52 // the flags
53 water = 0x01, 53 water = 0x01,
@@ -64,7 +64,7 @@ namespace OpenSim.Region.Physics.Manager
64 ClosestHit = 0x8000, 64 ClosestHit = 0x8000,
65 65
66 // some combinations 66 // some combinations
67 LSLPhanton = phantom | volumedtc, 67 LSLPhantom = phantom | volumedtc,
68 PrimsNonPhantom = nonphysical | physical, 68 PrimsNonPhantom = nonphysical | physical,
69 PrimsNonPhantomAgents = nonphysical | physical | agent, 69 PrimsNonPhantomAgents = nonphysical | physical | agent,
70 70
@@ -97,13 +97,20 @@ namespace OpenSim.Region.Physics.Manager
97// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 97// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
98 98
99 /// <summary> 99 /// <summary>
100 /// Name of this scene. Useful in debug messages to distinguish one OdeScene instance from another. 100 /// A unique identifying string for this instance of the physics engine.
101 /// Useful in debug messages to distinguish one OdeScene instance from another.
102 /// Usually set to include the region name that the physics engine is acting for.
101 /// </summary> 103 /// </summary>
102 public string Name { get; protected set; } 104 public string Name { get; protected set; }
103 105
106 /// <summary>
107 /// A string identifying the family of this physics engine. Most common values returned
108 /// are "OpenDynamicsEngine" and "BulletSim" but others are possible.
109 /// </summary>
110 public string EngineType { get; protected set; }
111
104 // The only thing that should register for this event is the SceneGraph 112 // The only thing that should register for this event is the SceneGraph
105 // Anything else could cause problems. 113 // Anything else could cause problems.
106
107 public event physicsCrash OnPhysicsCrash; 114 public event physicsCrash OnPhysicsCrash;
108 115
109 public static PhysicsScene Null 116 public static PhysicsScene Null
diff --git a/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/OpenSim/Region/Physics/Manager/ZeroMesher.cs
index 16846e6..80ecf66 100644
--- a/OpenSim/Region/Physics/Manager/ZeroMesher.cs
+++ b/OpenSim/Region/Physics/Manager/ZeroMesher.cs
@@ -64,16 +64,21 @@ namespace OpenSim.Region.Physics.Manager
64 { 64 {
65 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 65 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
66 { 66 {
67 return CreateMesh(primName, primShape, size, lod, false); 67 return CreateMesh(primName, primShape, size, lod, false, false);
68 } 68 }
69 69
70 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex,bool forOde) 70 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex,bool forOde)
71 { 71 {
72 return CreateMesh(primName, primShape, size, lod, false); 72 return CreateMesh(primName, primShape, size, lod, false);
73 } 73 }
74 74
75 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 75 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
76 { 76 {
77 return CreateMesh(primName, primShape, size, lod, false, false);
78 }
79
80 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
81 {
77 // Remove the reference to the encoded JPEG2000 data so it can be GCed 82 // Remove the reference to the encoded JPEG2000 data so it can be GCed
78 primShape.SculptData = OpenMetaverse.Utils.EmptyBytes; 83 primShape.SculptData = OpenMetaverse.Utils.EmptyBytes;
79 84
diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs
index 6970553..e6b32e7 100644
--- a/OpenSim/Region/Physics/Meshing/Mesh.cs
+++ b/OpenSim/Region/Physics/Meshing/Mesh.cs
@@ -226,7 +226,7 @@ namespace OpenSim.Region.Physics.Meshing
226 return result; 226 return result;
227 } 227 }
228 228
229 private float[] getVertexListAsFloat() 229 public float[] getVertexListAsFloat()
230 { 230 {
231 if (m_vertices == null) 231 if (m_vertices == null)
232 throw new NotSupportedException(); 232 throw new NotSupportedException();
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index f629c4d..d181b78 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -321,6 +321,9 @@ namespace OpenSim.Region.Physics.Meshing
321 321
322 if (primShape.SculptData.Length <= 0) 322 if (primShape.SculptData.Length <= 0)
323 { 323 {
324 // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this
325 // method twice - once before it has loaded sculpt data from the asset service and once afterwards.
326 // The first time will always call with unloaded SculptData if this needs to be uploaded.
324// m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName); 327// m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName);
325 return false; 328 return false;
326 } 329 }
@@ -699,16 +702,21 @@ namespace OpenSim.Region.Physics.Meshing
699 702
700 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 703 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
701 { 704 {
702 return CreateMesh(primName, primShape, size, lod, false); 705 return CreateMesh(primName, primShape, size, lod, false, true);
703 } 706 }
704 707
705 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde) 708 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde)
706 { 709 {
707 return CreateMesh(primName, primShape, size, lod, false); 710 return CreateMesh(primName, primShape, size, lod, false);
708 } 711 }
709 712
710 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 713 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
711 { 714 {
715 return CreateMesh(primName, primShape, size, lod, isPhysical, true);
716 }
717
718 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
719 {
712#if SPAM 720#if SPAM
713 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); 721 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
714#endif 722#endif
@@ -718,9 +726,12 @@ namespace OpenSim.Region.Physics.Meshing
718 726
719 // If this mesh has been created already, return it instead of creating another copy 727 // If this mesh has been created already, return it instead of creating another copy
720 // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory 728 // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory
721 key = primShape.GetMeshKey(size, lod); 729 if (shouldCache)
722 if (m_uniqueMeshes.TryGetValue(key, out mesh)) 730 {
723 return mesh; 731 key = primShape.GetMeshKey(size, lod);
732 if (m_uniqueMeshes.TryGetValue(key, out mesh))
733 return mesh;
734 }
724 735
725 if (size.X < 0.01f) size.X = 0.01f; 736 if (size.X < 0.01f) size.X = 0.01f;
726 if (size.Y < 0.01f) size.Y = 0.01f; 737 if (size.Y < 0.01f) size.Y = 0.01f;
@@ -743,7 +754,10 @@ namespace OpenSim.Region.Physics.Meshing
743 // trim the vertex and triangle lists to free up memory 754 // trim the vertex and triangle lists to free up memory
744 mesh.TrimExcess(); 755 mesh.TrimExcess();
745 756
746 m_uniqueMeshes.Add(key, mesh); 757 if (shouldCache)
758 {
759 m_uniqueMeshes.Add(key, mesh);
760 }
747 } 761 }
748 762
749 return mesh; 763 return mesh;
diff --git a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
index 4cc1731..bd70296 100644
--- a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
index 3c4f06a..f477ed1 100644
--- a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.5.*")] 58[assembly : AssemblyVersion("0.7.6.*")]
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index a59f63f..d09aa62 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -3367,6 +3367,11 @@ Console.WriteLine(" JointCreateFixed");
3367 _pbs.SculptData = new byte[asset.Data.Length]; 3367 _pbs.SculptData = new byte[asset.Data.Length];
3368 asset.Data.CopyTo(_pbs.SculptData, 0); 3368 asset.Data.CopyTo(_pbs.SculptData, 0);
3369// m_assetFailed = false; 3369// m_assetFailed = false;
3370
3371// m_log.DebugFormat(
3372// "[ODE PRIM]: Received mesh/sculpt data asset {0} with {1} bytes for {2} at {3} in {4}",
3373// _pbs.SculptTexture, _pbs.SculptData.Length, Name, _position, _parent_scene.Name);
3374
3370 m_taintshape = true; 3375 m_taintshape = true;
3371 _parent_scene.AddPhysicsActorTaint(this); 3376 _parent_scene.AddPhysicsActorTaint(this);
3372 } 3377 }
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 478dd95..07663b3 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -72,7 +72,7 @@ namespace OpenSim.Region.Physics.OdePlugin
72 // http://opensimulator.org/mantis/view.php?id=2750). 72 // http://opensimulator.org/mantis/view.php?id=2750).
73 d.InitODE(); 73 d.InitODE();
74 74
75 m_scene = new OdeScene(sceneIdentifier); 75 m_scene = new OdeScene(GetName(), sceneIdentifier);
76 } 76 }
77 77
78 return m_scene; 78 return m_scene;
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index d53bd90..6d7f079 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -526,11 +526,12 @@ namespace OpenSim.Region.Physics.OdePlugin
526 /// These settings need to be tweaked 'exactly' right or weird stuff happens. 526 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
527 /// </summary> 527 /// </summary>
528 /// <param value="name">Name of the scene. Useful in debug messages.</param> 528 /// <param value="name">Name of the scene. Useful in debug messages.</param>
529 public OdeScene(string name) 529 public OdeScene(string engineType, string name)
530 { 530 {
531 m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name); 531 m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name);
532 532
533 Name = name; 533 Name = name;
534 EngineType = engineType;
534 535
535 nearCallback = near; 536 nearCallback = near;
536 triCallback = TriCallback; 537 triCallback = TriCallback;
@@ -4095,8 +4096,8 @@ namespace OpenSim.Region.Physics.OdePlugin
4095 lock (_prims) 4096 lock (_prims)
4096 { 4097 {
4097 List<OdePrim> orderedPrims = new List<OdePrim>(_prims); 4098 List<OdePrim> orderedPrims = new List<OdePrim>(_prims);
4098 orderedPrims.OrderByDescending(p => p.CollisionScore).Take(25); 4099 orderedPrims.OrderByDescending(p => p.CollisionScore);
4099 topColliders = orderedPrims.ToDictionary(p => p.LocalID, p => p.CollisionScore); 4100 topColliders = orderedPrims.Take(25).ToDictionary(p => p.LocalID, p => p.CollisionScore);
4100 4101
4101 foreach (OdePrim p in _prims) 4102 foreach (OdePrim p in _prims)
4102 p.CollisionScore = 0; 4103 p.CollisionScore = 0;
diff --git a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
index cbc6b95..16404c6 100644
--- a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
+++ b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
@@ -32,13 +32,14 @@ using OpenMetaverse;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.OdePlugin; 34using OpenSim.Region.Physics.OdePlugin;
35using OpenSim.Tests.Common;
35using log4net; 36using log4net;
36using System.Reflection; 37using System.Reflection;
37 38
38namespace OpenSim.Region.Physics.OdePlugin.Tests 39namespace OpenSim.Region.Physics.OdePlugin.Tests
39{ 40{
40 [TestFixture] 41 [TestFixture]
41 public class ODETestClass 42 public class ODETestClass : OpenSimTestCase
42 { 43 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 45
diff --git a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
index d07df02..4289863 100644
--- a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.5.*")] 58[assembly : AssemblyVersion("0.7.6.*")]
diff --git a/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs b/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs
index e6b42e6..ed086dd 100644
--- a/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs
+++ b/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.Physics.POSPlugin
49 49
50 public PhysicsScene GetScene(string sceneIdentifier) 50 public PhysicsScene GetScene(string sceneIdentifier)
51 { 51 {
52 return new POSScene(sceneIdentifier); 52 return new POSScene(GetName(), sceneIdentifier);
53 } 53 }
54 54
55 public string GetName() 55 public string GetName()
diff --git a/OpenSim/Region/Physics/POSPlugin/POSScene.cs b/OpenSim/Region/Physics/POSPlugin/POSScene.cs
index 2f24a50..d30d482 100644
--- a/OpenSim/Region/Physics/POSPlugin/POSScene.cs
+++ b/OpenSim/Region/Physics/POSPlugin/POSScene.cs
@@ -43,8 +43,10 @@ namespace OpenSim.Region.Physics.POSPlugin
43 43
44 //protected internal string sceneIdentifier; 44 //protected internal string sceneIdentifier;
45 45
46 public POSScene(String _sceneIdentifier) 46 public POSScene(string engineType, String _sceneIdentifier)
47 { 47 {
48 EngineType = engineType;
49 Name = EngineType + "/" + _sceneIdentifier;
48 //sceneIdentifier = _sceneIdentifier; 50 //sceneIdentifier = _sceneIdentifier;
49 } 51 }
50 52
diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
index b67422f..fa06926 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
@@ -301,7 +301,7 @@ namespace OpenSim.Region.Physics.Meshing
301 return result; 301 return result;
302 } 302 }
303 303
304 private float[] getVertexListAsFloat() 304 public float[] getVertexListAsFloat()
305 { 305 {
306 if (m_bdata.m_vertices == null) 306 if (m_bdata.m_vertices == null)
307 throw new NotSupportedException(); 307 throw new NotSupportedException();
diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
index 6e1a105..00cbfbd 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
@@ -1031,12 +1031,12 @@ namespace OpenSim.Region.Physics.Meshing
1031 1031
1032 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 1032 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
1033 { 1033 {
1034 return CreateMesh(primName, primShape, size, lod, false,false,false); 1034 return CreateMesh(primName, primShape, size, lod, false,false,false,false);
1035 } 1035 }
1036 1036
1037 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 1037 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
1038 { 1038 {
1039 return CreateMesh(primName, primShape, size, lod, false,false,false); 1039 return CreateMesh(primName, primShape, size, lod, false,false,false,false);
1040 } 1040 }
1041 1041
1042 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) 1042 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
@@ -1080,7 +1080,7 @@ namespace OpenSim.Region.Physics.Meshing
1080 1080
1081 private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f); 1081 private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f);
1082 1082
1083 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde) 1083 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde)
1084 { 1084 {
1085#if SPAM 1085#if SPAM
1086 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); 1086 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
index 5030cec..0df71eb 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
@@ -448,7 +448,7 @@ namespace OpenSim.Region.Physics.OdePlugin
448 else 448 else
449 { 449 {
450 repData.meshState = MeshState.needMesh; 450 repData.meshState = MeshState.needMesh;
451 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true); 451 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, false, convex, true);
452 if (mesh == null) 452 if (mesh == null)
453 { 453 {
454 repData.meshState = MeshState.MeshFailed; 454 repData.meshState = MeshState.MeshFailed;
@@ -513,7 +513,7 @@ namespace OpenSim.Region.Physics.OdePlugin
513 clod = (int)LevelOfDetail.Low; 513 clod = (int)LevelOfDetail.Low;
514 } 514 }
515 515
516 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true); 516 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, false, convex, true);
517 517
518 if (mesh == null) 518 if (mesh == null)
519 { 519 {
@@ -929,4 +929,4 @@ namespace OpenSim.Region.Physics.OdePlugin
929 repData.actor.Name); 929 repData.actor.Name);
930 } 930 }
931 } 931 }
932} \ No newline at end of file 932}
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
index 4f598ea..2923ccf 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
@@ -300,9 +300,9 @@ namespace OpenSim.Region.Physics.OdePlugin
300 ((ProbeSphereCallback)req.callbackMethod)(cresult); 300 ((ProbeSphereCallback)req.callbackMethod)(cresult);
301 } 301 }
302 302
303 private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton; 303 private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhantom;
304// private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton; 304// private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
305 private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton; 305 private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhantom;
306 306
307 private void doSpaceRay(ODERayRequest req) 307 private void doSpaceRay(ODERayRequest req)
308 { 308 {
@@ -680,4 +680,4 @@ namespace OpenSim.Region.Physics.OdePlugin
680 public RayFilterFlags filter; 680 public RayFilterFlags filter;
681 public Quaternion orientation; 681 public Quaternion orientation;
682 } 682 }
683} \ No newline at end of file 683}
diff --git a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
index 085eb59..ca945b5 100644
--- a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
index 2027ca6..30e99b0 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
@@ -26,9 +26,11 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Threading;
29using OpenMetaverse; 30using OpenMetaverse;
30using OpenSim.Framework; 31using OpenSim.Framework;
31using OpenSim.Region.Framework.Scenes; 32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Region.ScriptEngine.Shared;
32 34
33namespace OpenSim.Region.ScriptEngine.Interfaces 35namespace OpenSim.Region.ScriptEngine.Interfaces
34{ 36{
@@ -38,11 +40,12 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
38 /// Initialize the API 40 /// Initialize the API
39 /// </summary> 41 /// </summary>
40 /// <remarks> 42 /// <remarks>
41 /// Each API has an identifier, which is used to load the 43 /// Each API has an identifier, which is used to load the proper runtime assembly at load time.
42 /// proper runtime assembly at load time. 44 /// <param name='scriptEngine'>/param>
43 /// <param name='engine'>/param> 45 /// <param name='host'>/param>
44 /// <param name='part'></param> 46 /// <param name='item'>/param>
45 /// <param name='item'></param> 47 /// <param name='coopSleepHandle'>/param>
46 void Initialize(IScriptEngine engine, SceneObjectPart part, TaskInventoryItem item); 48 void Initialize(
49 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle);
47 } 50 }
48} \ No newline at end of file 51} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
index 17c2708..b8fdd01 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
@@ -25,16 +25,17 @@
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 log4net;
29using System; 28using System;
30using OpenSim.Region.ScriptEngine.Shared; 29using System.Reflection;
30using OpenSim.Framework;
31using OpenSim.Region.Framework.Scenes; 31using OpenSim.Region.Framework.Scenes;
32using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
33using OpenMetaverse;
34using Nini.Config;
35using OpenSim.Region.ScriptEngine.Interfaces; 33using OpenSim.Region.ScriptEngine.Interfaces;
34using OpenSim.Region.ScriptEngine.Shared;
36using Amib.Threading; 35using Amib.Threading;
37using OpenSim.Framework; 36using log4net;
37using Nini.Config;
38using OpenMetaverse;
38 39
39namespace OpenSim.Region.ScriptEngine.Interfaces 40namespace OpenSim.Region.ScriptEngine.Interfaces
40{ 41{
@@ -76,6 +77,38 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
76 IConfigSource ConfigSource { get; } 77 IConfigSource ConfigSource { get; }
77 string ScriptEngineName { get; } 78 string ScriptEngineName { get; }
78 string ScriptEnginePath { get; } 79 string ScriptEnginePath { get; }
80
81 /// <summary>
82 /// Return the name of the class that will be used for all running scripts.
83 /// </summary>
84 /// <remarks>
85 /// Each class goes in its own assembly so we don't need to otherwise distinguish the class name.
86 /// </remarks>
87 string ScriptClassName { get; }
88
89 /// <summary>
90 /// Return the name of the base class that will be used for all running scripts.
91 /// </summary>
92 string ScriptBaseClassName { get; }
93
94 /// <summary>
95 /// Assemblies that need to be referenced when compiling scripts.
96 /// </summary>
97 /// <remarks>
98 /// These are currently additional to those always referenced by the compiler, BUT THIS MAY CHANGE IN THE
99 /// FUTURE.
100 /// This can be null if there are no additional assemblies.
101 /// </remarks>
102 string[] ScriptReferencedAssemblies { get; }
103
104 /// <summary>
105 /// Parameters for the generated script's constructor.
106 /// </summary>
107 /// <remarks>
108 /// Can be null if there are no parameters
109 /// </remarks>
110 ParameterInfo[] ScriptBaseClassParameters { get; }
111
79 IScriptApi GetApi(UUID itemID, string name); 112 IScriptApi GetApi(UUID itemID, string name);
80 } 113 }
81} 114}
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index b04f6b6..f68612c 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -28,9 +28,11 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Threading;
31using OpenMetaverse; 32using OpenMetaverse;
32using log4net; 33using log4net;
33using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.Framework.Scenes;
34using OpenSim.Region.ScriptEngine.Shared; 36using OpenSim.Region.ScriptEngine.Shared;
35using OpenSim.Region.ScriptEngine.Interfaces; 37using OpenSim.Region.ScriptEngine.Interfaces;
36 38
@@ -59,6 +61,18 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
59 public interface IScriptInstance 61 public interface IScriptInstance
60 { 62 {
61 /// <summary> 63 /// <summary>
64 /// Debug level for this script instance.
65 /// </summary>
66 /// <remarks>
67 /// Level == 0, no extra data is logged.
68 /// Level >= 1, state changes are logged.
69 /// Level >= 2, event firing is logged.
70 /// <value>
71 /// The debug level.
72 /// </value>
73 int DebugLevel { get; set; }
74
75 /// <summary>
62 /// Is the script currently running? 76 /// Is the script currently running?
63 /// </summary> 77 /// </summary>
64 bool Running { get; set; } 78 bool Running { get; set; }
@@ -93,6 +107,11 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
93 /// </summary> 107 /// </summary>
94 long MeasurementPeriodExecutionTime { get; } 108 long MeasurementPeriodExecutionTime { get; }
95 109
110 /// <summary>
111 /// Scene part in which this script instance is contained.
112 /// </summary>
113 SceneObjectPart Part { get; }
114
96 IScriptEngine Engine { get; } 115 IScriptEngine Engine { get; }
97 UUID AppDomain { get; set; } 116 UUID AppDomain { get; set; }
98 string PrimName { get; } 117 string PrimName { get; }
@@ -112,8 +131,24 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
112 131
113 uint LocalID { get; } 132 uint LocalID { get; }
114 UUID AssetID { get; } 133 UUID AssetID { get; }
134
135 /// <summary>
136 /// Inventory item containing the script used.
137 /// </summary>
138 TaskInventoryItem ScriptTask { get; }
139
115 Queue EventQueue { get; } 140 Queue EventQueue { get; }
116 141
142 /// <summary>
143 /// Number of events queued for processing.
144 /// </summary>
145 long EventsQueued { get; }
146
147 /// <summary>
148 /// Number of events processed by this script instance.
149 /// </summary>
150 long EventsProcessed { get; }
151
117 void ClearQueue(); 152 void ClearQueue();
118 int StartParam { get; set; } 153 int StartParam { get; set; }
119 154
@@ -125,7 +160,13 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
125 /// <summary> 160 /// <summary>
126 /// Stop the script instance. 161 /// Stop the script instance.
127 /// </summary> 162 /// </summary>
163 /// <remarks>
164 /// This must not be called by a thread that is in the process of handling an event for this script. Otherwise
165 /// there is a danger that it will self-abort and not complete the reset.
166 /// </remarks>
128 /// <param name="timeout"></param> 167 /// <param name="timeout"></param>
168 /// How many milliseconds we will wait for an existing script event to finish before
169 /// forcibly aborting that event.
129 /// <returns>true if the script was successfully stopped, false otherwise</returns> 170 /// <returns>true if the script was successfully stopped, false otherwise</returns>
130 bool Stop(int timeout); 171 bool Stop(int timeout);
131 172
@@ -147,8 +188,31 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
147 object EventProcessor(); 188 object EventProcessor();
148 189
149 int EventTime(); 190 int EventTime();
150 void ResetScript(); 191
192 /// <summary>
193 /// Reset the script.
194 /// </summary>
195 /// <remarks>
196 /// This must not be called by a thread that is in the process of handling an event for this script. Otherwise
197 /// there is a danger that it will self-abort and not complete the reset. Such a thread must call
198 /// ApiResetScript() instead.
199 /// </remarks>
200 /// <param name='timeout'>
201 /// How many milliseconds we will wait for an existing script event to finish before
202 /// forcibly aborting that event prior to script reset.
203 /// </param>
204 void ResetScript(int timeout);
205
206 /// <summary>
207 /// Reset the script.
208 /// </summary>
209 /// <remarks>
210 /// This must not be called by any thread other than the one executing the scripts current event. This is
211 /// because there is no wait or abort logic if another thread is in the middle of processing a script event.
212 /// Such an external thread should use ResetScript() instead.
213 /// </remarks>
151 void ApiResetScript(); 214 void ApiResetScript();
215
152 Dictionary<string, object> GetVars(); 216 Dictionary<string, object> GetVars();
153 void SetVars(Dictionary<string, object> vars); 217 void SetVars(Dictionary<string, object> vars);
154 DetectParams GetDetectParams(int idx); 218 DetectParams GetDetectParams(int idx);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
index b5fa6de..fce8ff8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Threading;
29using System.Reflection; 30using System.Reflection;
30using System.Collections; 31using System.Collections;
31using System.Collections.Generic; 32using System.Collections.Generic;
@@ -62,7 +63,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
62 internal TaskInventoryItem m_item; 63 internal TaskInventoryItem m_item;
63 internal bool m_CMFunctionsEnabled = false; 64 internal bool m_CMFunctionsEnabled = false;
64 65
65 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 66 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
66 { 67 {
67 m_ScriptEngine = ScriptEngine; 68 m_ScriptEngine = ScriptEngine;
68 m_host = host; 69 m_host = host;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 6685764..f9ee590 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -48,6 +48,7 @@ using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Framework.Scenes.Serialization; 49using OpenSim.Region.Framework.Scenes.Serialization;
50using OpenSim.Region.Framework.Scenes.Animation; 50using OpenSim.Region.Framework.Scenes.Animation;
51using OpenSim.Region.Framework.Scenes.Scripting;
51using OpenSim.Region.Physics.Manager; 52using OpenSim.Region.Physics.Manager;
52using OpenSim.Region.ScriptEngine.Shared; 53using OpenSim.Region.ScriptEngine.Shared;
53using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 54using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
@@ -87,10 +88,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
87 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi 88 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
88 { 89 {
89 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 90 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
91
90 protected IScriptEngine m_ScriptEngine; 92 protected IScriptEngine m_ScriptEngine;
91 protected SceneObjectPart m_host; 93 protected SceneObjectPart m_host;
92 94
93 /// <summary> 95 /// <summary>
96 /// Used for script sleeps when we are using co-operative script termination.
97 /// </summary>
98 /// <remarks>null if co-operative script termination is not active</remarks>
99 WaitHandle m_coopSleepHandle;
100
101 /// <summary>
94 /// The item that hosts this script 102 /// The item that hosts this script
95 /// </summary> 103 /// </summary>
96 protected TaskInventoryItem m_item; 104 protected TaskInventoryItem m_item;
@@ -100,6 +108,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
100 protected float m_ScriptDelayFactor = 1.0f; 108 protected float m_ScriptDelayFactor = 1.0f;
101 protected float m_ScriptDistanceFactor = 1.0f; 109 protected float m_ScriptDistanceFactor = 1.0f;
102 protected float m_MinTimerInterval = 0.5f; 110 protected float m_MinTimerInterval = 0.5f;
111 protected float m_recoilScaleFactor = 0.0f;
103 112
104 protected DateTime m_timer = DateTime.Now; 113 protected DateTime m_timer = DateTime.Now;
105 protected bool m_waitingForScriptAnswer = false; 114 protected bool m_waitingForScriptAnswer = false;
@@ -141,33 +150,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
141 {"TURNRIGHT", "Turning Right"} 150 {"TURNRIGHT", "Turning Right"}
142 }; 151 };
143 152
144 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 153 public void Initialize(
154 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
145 { 155 {
146/*
147 m_ShoutSayTimer = new Timer(1000);
148 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
149 m_ShoutSayTimer.AutoReset = true;
150 m_ShoutSayTimer.Start();
151*/
152 m_lastSayShoutCheck = DateTime.UtcNow; 156 m_lastSayShoutCheck = DateTime.UtcNow;
153 157
154 m_ScriptEngine = ScriptEngine; 158 m_ScriptEngine = scriptEngine;
155 m_host = host; 159 m_host = host;
156 m_item = item; 160 m_item = item;
157 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 161 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
162 m_coopSleepHandle = coopSleepHandle;
158 163
159 LoadLimits(); // read script limits from config. 164 LoadConfig();
160 165
161 m_TransferModule = 166 m_TransferModule =
162 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 167 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
163 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 168 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
164 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); 169 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
165 170
166 AsyncCommands = new AsyncCommandManager(ScriptEngine); 171 AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
167 } 172 }
168 173
169 /* load configuration items that affect script, object and run-time behavior. */ 174 /// <summary>
170 private void LoadLimits() 175 /// Load configuration items that affect script, object and run-time behavior. */
176 /// </summary>
177 private void LoadConfig()
171 { 178 {
172 m_ScriptDelayFactor = 179 m_ScriptDelayFactor =
173 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 180 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -181,12 +188,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
181 m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255); 188 m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255);
182 if (m_notecardLineReadCharsMax > 65535) 189 if (m_notecardLineReadCharsMax > 65535)
183 m_notecardLineReadCharsMax = 65535; 190 m_notecardLineReadCharsMax = 65535;
191
184 // load limits for particular subsystems. 192 // load limits for particular subsystems.
185 IConfig SMTPConfig; 193 IConfig SMTPConfig;
186 if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) { 194 if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) {
187 // there's an smtp config, so load in the snooze time. 195 // there's an smtp config, so load in the snooze time.
188 EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); 196 EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
189 } 197 }
198
199 // Rezzing an object with a velocity can create recoil. This feature seems to have been
200 // removed from recent versions of SL. The code computes recoil (vel*mass) and scales
201 // it by this factor. May be zero to turn off recoil all together.
202 m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
190 } 203 }
191 204
192 public override Object InitializeLifetimeService() 205 public override Object InitializeLifetimeService()
@@ -207,7 +220,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
207 delay = (int)((float)delay * m_ScriptDelayFactor); 220 delay = (int)((float)delay * m_ScriptDelayFactor);
208 if (delay == 0) 221 if (delay == 0)
209 return; 222 return;
210 System.Threading.Thread.Sleep(delay); 223
224 Sleep(delay);
225 }
226
227 protected virtual void Sleep(int delay)
228 {
229 if (m_coopSleepHandle == null)
230 System.Threading.Thread.Sleep(delay);
231 else
232 CheckForCoopTermination(delay);
233 }
234
235 /// <summary>
236 /// Check for co-operative termination.
237 /// </summary>
238 /// <param name='delay'>If called with 0, then just the check is performed with no wait.</param>
239 protected virtual void CheckForCoopTermination(int delay)
240 {
241 if (m_coopSleepHandle.WaitOne(delay))
242 throw new ScriptCoopStopException();
211 } 243 }
212 244
213 public Scene World 245 public Scene World
@@ -392,79 +424,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
392 } 424 }
393 } 425 }
394 426
395 protected UUID InventoryKey(string name, int type)
396 {
397 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
398
399 if (item != null && item.Type == type)
400 return item.AssetID;
401 else
402 return UUID.Zero;
403 }
404
405 /// <summary>
406 /// accepts a valid UUID, -or- a name of an inventory item.
407 /// Returns a valid UUID or UUID.Zero if key invalid and item not found
408 /// in prim inventory.
409 /// </summary>
410 /// <param name="k"></param>
411 /// <returns></returns>
412 protected UUID KeyOrName(string k)
413 {
414 UUID key;
415
416 // if we can parse the string as a key, use it.
417 // else try to locate the name in inventory of object. found returns key,
418 // not found returns UUID.Zero
419 if (!UUID.TryParse(k, out key))
420 {
421 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k);
422
423 if (item != null)
424 key = item.AssetID;
425 else
426 key = UUID.Zero;
427 }
428
429 return key;
430 }
431
432 /// <summary>
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)
440 {
441 UUID key;
442
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;
466 }
467
468 //These are the implementations of the various ll-functions used by the LSL scripts. 427 //These are the implementations of the various ll-functions used by the LSL scripts.
469 public LSL_Float llSin(double f) 428 public LSL_Float llSin(double f)
470 { 429 {
@@ -1483,19 +1442,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1483 return 0; 1442 return 0;
1484 1443
1485 case ScriptBaseClass.STATUS_ROTATE_X: 1444 case ScriptBaseClass.STATUS_ROTATE_X:
1486 if (m_host.GetAxisRotation(2) == 2) 1445 // if (m_host.GetAxisRotation(2) != 0)
1446 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
1487 return 1; 1447 return 1;
1488 else 1448 else
1489 return 0; 1449 return 0;
1490 1450
1491 case ScriptBaseClass.STATUS_ROTATE_Y: 1451 case ScriptBaseClass.STATUS_ROTATE_Y:
1492 if (m_host.GetAxisRotation(4) == 4) 1452 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
1493 return 1; 1453 return 1;
1494 else 1454 else
1495 return 0; 1455 return 0;
1496 1456
1497 case ScriptBaseClass.STATUS_ROTATE_Z: 1457 case ScriptBaseClass.STATUS_ROTATE_Z:
1498 if (m_host.GetAxisRotation(8) == 8) 1458 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
1499 return 1; 1459 return 1;
1500 else 1460 else
1501 return 0; 1461 return 0;
@@ -1875,10 +1835,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1875 part.Shape.FlexiForceX = (float)Force.x; 1835 part.Shape.FlexiForceX = (float)Force.x;
1876 part.Shape.FlexiForceY = (float)Force.y; 1836 part.Shape.FlexiForceY = (float)Force.y;
1877 part.Shape.FlexiForceZ = (float)Force.z; 1837 part.Shape.FlexiForceZ = (float)Force.z;
1878 part.Shape.PathCurve = 0x80; 1838 part.Shape.PathCurve = (byte)Extrusion.Flexible;
1879 part.ParentGroup.HasGroupChanged = true; 1839 }
1880 part.ScheduleFullUpdate(); 1840 else
1841 {
1842 // Other values not set, they do not seem to be sent to the viewer
1843 // Setting PathCurve appears to be what actually toggles the check box and turns Flexi on and off
1844 part.Shape.PathCurve = (byte)Extrusion.Straight;
1845 part.Shape.FlexiEntry = false;
1881 } 1846 }
1847 part.ParentGroup.HasGroupChanged = true;
1848 part.ScheduleFullUpdate();
1882 } 1849 }
1883 1850
1884 /// <summary> 1851 /// <summary>
@@ -1996,7 +1963,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1996 1963
1997 UUID textureID = new UUID(); 1964 UUID textureID = new UUID();
1998 1965
1999 textureID = InventoryKey(texture, (int)AssetType.Texture); 1966 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
2000 if (textureID == UUID.Zero) 1967 if (textureID == UUID.Zero)
2001 { 1968 {
2002 if (!UUID.TryParse(texture, out textureID)) 1969 if (!UUID.TryParse(texture, out textureID))
@@ -2712,7 +2679,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2712 if (m_SoundModule != null) 2679 if (m_SoundModule != null)
2713 { 2680 {
2714 m_SoundModule.SendSound(m_host.UUID, 2681 m_SoundModule.SendSound(m_host.UUID,
2715 KeyOrName(sound, AssetType.Sound), volume, false, 0, 2682 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0,
2716 0, false, false); 2683 0, false, false);
2717 } 2684 }
2718 } 2685 }
@@ -2722,7 +2689,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2722 m_host.AddScriptLPS(1); 2689 m_host.AddScriptLPS(1);
2723 if (m_SoundModule != null) 2690 if (m_SoundModule != null)
2724 { 2691 {
2725 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), 2692 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2726 volume, 20, false); 2693 volume, 20, false);
2727 } 2694 }
2728 } 2695 }
@@ -2732,7 +2699,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2732 m_host.AddScriptLPS(1); 2699 m_host.AddScriptLPS(1);
2733 if (m_SoundModule != null) 2700 if (m_SoundModule != null)
2734 { 2701 {
2735 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), 2702 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2736 volume, 20, true); 2703 volume, 20, true);
2737 } 2704 }
2738 } 2705 }
@@ -2754,7 +2721,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2754 if (m_SoundModule != null) 2721 if (m_SoundModule != null)
2755 { 2722 {
2756 m_SoundModule.SendSound(m_host.UUID, 2723 m_SoundModule.SendSound(m_host.UUID,
2757 KeyOrName(sound, AssetType.Sound), volume, false, 0, 2724 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0,
2758 0, true, false); 2725 0, true, false);
2759 } 2726 }
2760 } 2727 }
@@ -2766,7 +2733,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2766 if (m_SoundModule != null) 2733 if (m_SoundModule != null)
2767 { 2734 {
2768 m_SoundModule.SendSound(m_host.UUID, 2735 m_SoundModule.SendSound(m_host.UUID,
2769 KeyOrName(sound, AssetType.Sound), volume, true, 0, 0, 2736 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0,
2770 false, false); 2737 false, false);
2771 } 2738 }
2772 } 2739 }
@@ -2783,7 +2750,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2783 { 2750 {
2784 m_host.AddScriptLPS(1); 2751 m_host.AddScriptLPS(1);
2785 if (m_SoundModule != null) 2752 if (m_SoundModule != null)
2786 m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0); 2753 m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0);
2787 ScriptSleep(1000); 2754 ScriptSleep(1000);
2788 } 2755 }
2789 2756
@@ -3141,11 +3108,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3141 3108
3142 PhysicsActor pa = new_group.RootPart.PhysActor; 3109 PhysicsActor pa = new_group.RootPart.PhysActor;
3143 3110
3111 //Recoil.
3144 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3112 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3145 { 3113 {
3146 float groupmass = new_group.GetMass(); 3114 float groupmass = new_group.GetMass();
3147 vel *= -groupmass; 3115 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3148 llApplyImpulse(vel, 0); 3116 if (recoil != Vector3.Zero)
3117 {
3118 llApplyImpulse(recoil, 0);
3119 }
3149 } 3120 }
3150 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3121 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3151 return; 3122 return;
@@ -3220,7 +3191,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3220 { 3191 {
3221// m_log.Info("llSleep snoozing " + sec + "s."); 3192// m_log.Info("llSleep snoozing " + sec + "s.");
3222 m_host.AddScriptLPS(1); 3193 m_host.AddScriptLPS(1);
3223 Thread.Sleep((int)(sec * 1000)); 3194
3195 Sleep((int)(sec * 1000));
3224 } 3196 }
3225 3197
3226 public LSL_Float llGetMass() 3198 public LSL_Float llGetMass()
@@ -3322,7 +3294,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3322 /// <summary> 3294 /// <summary>
3323 /// Attach the object containing this script to the avatar that owns it. 3295 /// Attach the object containing this script to the avatar that owns it.
3324 /// </summary> 3296 /// </summary>
3325 /// <param name='attachment'>The attachment point (e.g. ATTACH_CHEST)</param> 3297 /// <param name='attachmentPoint'>
3298 /// The attachment point (e.g. <see cref="OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass.ATTACH_CHEST">ATTACH_CHEST</see>)
3299 /// </param>
3326 /// <returns>true if the attach suceeded, false if it did not</returns> 3300 /// <returns>true if the attach suceeded, false if it did not</returns>
3327 public bool AttachToAvatar(int attachmentPoint) 3301 public bool AttachToAvatar(int attachmentPoint)
3328 { 3302 {
@@ -3653,7 +3627,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3653 if (presence != null) 3627 if (presence != null)
3654 { 3628 {
3655 // Do NOT try to parse UUID, animations cannot be triggered by ID 3629 // Do NOT try to parse UUID, animations cannot be triggered by ID
3656 UUID animID = InventoryKey(anim, (int)AssetType.Animation); 3630 UUID animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation);
3657 if (animID == UUID.Zero) 3631 if (animID == UUID.Zero)
3658 presence.Animator.AddAnimation(anim, m_host.UUID); 3632 presence.Animator.AddAnimation(anim, m_host.UUID);
3659 else 3633 else
@@ -3675,12 +3649,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3675 3649
3676 if (presence != null) 3650 if (presence != null)
3677 { 3651 {
3678 UUID animID = KeyOrName(anim); 3652 UUID animID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, anim);
3679 3653
3680 if (animID == UUID.Zero) 3654 if (animID == UUID.Zero)
3681 presence.Animator.RemoveAnimation(anim); 3655 presence.Animator.RemoveAnimation(anim);
3682 else 3656 else
3683 presence.Animator.RemoveAnimation(animID); 3657 presence.Animator.RemoveAnimation(animID, true);
3684 } 3658 }
3685 } 3659 }
3686 } 3660 }
@@ -3753,21 +3727,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3753 } 3727 }
3754 else 3728 else
3755 { 3729 {
3756 bool sitting = false; 3730 if (m_host.ParentGroup.GetSittingAvatars().Contains(agentID))
3757 if (m_host.SitTargetAvatar == agentID)
3758 {
3759 sitting = true;
3760 }
3761 else
3762 {
3763 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3764 {
3765 if (p.SitTargetAvatar == agentID)
3766 sitting = true;
3767 }
3768 }
3769
3770 if (sitting)
3771 { 3731 {
3772 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3732 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3773 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3733 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
@@ -3809,7 +3769,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3809 INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); 3769 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
3810 if (npcModule != null && npcModule.IsNPC(agentID, World)) 3770 if (npcModule != null && npcModule.IsNPC(agentID, World))
3811 { 3771 {
3812 if (agentID == m_host.ParentGroup.OwnerID || npcModule.GetOwner(agentID) == m_host.ParentGroup.OwnerID) 3772 if (npcModule.CheckPermissions(agentID, m_host.OwnerID))
3813 { 3773 {
3814 lock (m_host.TaskInventory) 3774 lock (m_host.TaskInventory)
3815 { 3775 {
@@ -4184,62 +4144,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4184 public LSL_String llGetLinkName(int linknum) 4144 public LSL_String llGetLinkName(int linknum)
4185 { 4145 {
4186 m_host.AddScriptLPS(1); 4146 m_host.AddScriptLPS(1);
4187 // simplest case, this prims link number
4188 if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS)
4189 return m_host.Name;
4190
4191 // parse for sitting avatare-names
4192 List<String> nametable = new List<String>();
4193 World.ForEachRootScenePresence(delegate(ScenePresence presence)
4194 {
4195 SceneObjectPart sitPart = presence.ParentPart;
4196 if (sitPart != null && m_host.ParentGroup.ContainsPart(sitPart.LocalId))
4197 nametable.Add(presence.ControllingClient.Name);
4198 });
4199 4147
4200 int totalprims = m_host.ParentGroup.PrimCount + nametable.Count; 4148 if (linknum < 0)
4201 if (totalprims > m_host.ParentGroup.PrimCount)
4202 { 4149 {
4203 // sitting Avatar-Name with negativ linknum / SinglePrim 4150 if (linknum == ScriptBaseClass.LINK_THIS)
4204 if (linknum < 0 && m_host.ParentGroup.PrimCount == 1 && nametable.Count == 1)
4205 return nametable[0];
4206 // Prim-Name / SinglePrim Sitting Avatar
4207 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && nametable.Count == 1)
4208 return m_host.Name; 4151 return m_host.Name;
4209 // LinkNumber > of Real PrimSet = AvatarName 4152 else
4210 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims) 4153 return ScriptBaseClass.NULL_KEY;
4211 return nametable[totalprims - linknum];
4212 } 4154 }
4213 4155
4214 // Single prim 4156 int actualPrimCount = m_host.ParentGroup.PrimCount;
4215 if (m_host.LinkNum == 0) 4157 List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars();
4158 int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count;
4159
4160 // Special case for a single prim. In this case the linknum is zero. However, this will not match a single
4161 // prim that has any avatars sat upon it (in which case the root prim is link 1).
4162 if (linknum == 0)
4216 { 4163 {
4217 if (linknum == 0 || linknum == ScriptBaseClass.LINK_ROOT) 4164 if (actualPrimCount == 1 && sittingAvatarIds.Count == 0)
4218 return m_host.Name; 4165 return m_host.Name;
4219 else
4220 return UUID.Zero.ToString();
4221 }
4222 4166
4223 // Link set 4167 return ScriptBaseClass.NULL_KEY;
4224 SceneObjectPart part = null; 4168 }
4225 if (m_host.LinkNum == 1) // this is the Root prim 4169 // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but
4170 // here we must match 1 (ScriptBaseClass.LINK_ROOT).
4171 else if (linknum == 1 && actualPrimCount == 1)
4226 { 4172 {
4227 if (linknum < 0) 4173 if (sittingAvatarIds.Count > 0)
4228 part = m_host.ParentGroup.GetLinkNumPart(2); 4174 return m_host.ParentGroup.RootPart.Name;
4229 else 4175 else
4230 part = m_host.ParentGroup.GetLinkNumPart(linknum); 4176 return ScriptBaseClass.NULL_KEY;
4231 } 4177 }
4232 else // this is a child prim 4178 else if (linknum <= adjustedPrimCount)
4233 { 4179 {
4234 if (linknum < 2) 4180 if (linknum <= actualPrimCount)
4235 part = m_host.ParentGroup.GetLinkNumPart(1); 4181 {
4182 return m_host.ParentGroup.GetLinkNumPart(linknum).Name;
4183 }
4236 else 4184 else
4237 part = m_host.ParentGroup.GetLinkNumPart(linknum); 4185 {
4186 ScenePresence sp = World.GetScenePresence(sittingAvatarIds[linknum - actualPrimCount - 1]);
4187 if (sp != null)
4188 return sp.Name;
4189 else
4190 return ScriptBaseClass.NULL_KEY;
4191 }
4238 } 4192 }
4239 if (part != null)
4240 return part.Name;
4241 else 4193 else
4242 return UUID.Zero.ToString(); 4194 {
4195 return ScriptBaseClass.NULL_KEY;
4196 }
4243 } 4197 }
4244 4198
4245 public LSL_Integer llGetInventoryNumber(int type) 4199 public LSL_Integer llGetInventoryNumber(int type)
@@ -4691,7 +4645,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4691 4645
4692 private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt) 4646 private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt)
4693 { 4647 {
4694 UUID assetID = KeyOrName(destination); 4648 UUID assetID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, destination);
4695 4649
4696 // The destinaion is not an asset ID and also doesn't name a landmark. 4650 // The destinaion is not an asset ID and also doesn't name a landmark.
4697 // Use it as a sim name 4651 // Use it as a sim name
@@ -4764,7 +4718,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4764 return; 4718 return;
4765 } 4719 }
4766 // TODO: Parameter check logic required. 4720 // TODO: Parameter check logic required.
4767 m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound); 4721 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
4768 m_host.CollisionSoundVolume = (float)impact_volume; 4722 m_host.CollisionSoundVolume = (float)impact_volume;
4769 m_host.CollisionSoundType = 1; 4723 m_host.CollisionSoundType = 1;
4770 } 4724 }
@@ -5851,9 +5805,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5851 } 5805 }
5852 5806
5853 /// <summary> 5807 /// <summary>
5854 /// Insert the list identified by <src> into the 5808 /// Insert the list identified by <paramref name="src"/> into the
5855 /// list designated by <dest> such that the first 5809 /// list designated by <paramref name="dest"/> such that the first
5856 /// new element has the index specified by <index> 5810 /// new element has the index specified by <paramref name="index"/>
5857 /// </summary> 5811 /// </summary>
5858 5812
5859 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) 5813 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
@@ -6219,13 +6173,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6219 if (parcelOwned && land.LandData.OwnerID == id || 6173 if (parcelOwned && land.LandData.OwnerID == id ||
6220 parcel && land.LandData.GlobalID == id) 6174 parcel && land.LandData.GlobalID == id)
6221 { 6175 {
6222 result.Add(ssp.UUID.ToString()); 6176 result.Add(new LSL_Key(ssp.UUID.ToString()));
6223 } 6177 }
6224 } 6178 }
6225 } 6179 }
6226 else 6180 else
6227 { 6181 {
6228 result.Add(ssp.UUID.ToString()); 6182 result.Add(new LSL_Key(ssp.UUID.ToString()));
6229 } 6183 }
6230 } 6184 }
6231 // Maximum of 100 results 6185 // Maximum of 100 results
@@ -6329,7 +6283,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6329 if (m_SoundModule != null) 6283 if (m_SoundModule != null)
6330 { 6284 {
6331 m_SoundModule.TriggerSoundLimited(m_host.UUID, 6285 m_SoundModule.TriggerSoundLimited(m_host.UUID,
6332 KeyOrName(sound, AssetType.Sound), volume, 6286 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume,
6333 bottom_south_west, top_north_east); 6287 bottom_south_west, top_north_east);
6334 } 6288 }
6335 } 6289 }
@@ -6686,6 +6640,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6686 ps.BurstSpeedMax = 1.0f; 6640 ps.BurstSpeedMax = 1.0f;
6687 ps.BurstRate = 0.1f; 6641 ps.BurstRate = 0.1f;
6688 ps.PartMaxAge = 10.0f; 6642 ps.PartMaxAge = 10.0f;
6643 ps.BurstPartCount = 1;
6689 return ps; 6644 return ps;
6690 } 6645 }
6691 6646
@@ -6707,10 +6662,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6707 SetParticleSystem(m_host, rules); 6662 SetParticleSystem(m_host, rules);
6708 } 6663 }
6709 6664
6710 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) 6665 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6711 { 6666 {
6712
6713
6714 if (rules.Length == 0) 6667 if (rules.Length == 0)
6715 { 6668 {
6716 part.RemoveParticleSystem(); 6669 part.RemoveParticleSystem();
@@ -6801,7 +6754,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6801 break; 6754 break;
6802 6755
6803 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: 6756 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
6804 prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1)); 6757 prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1));
6805 break; 6758 break;
6806 6759
6807 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE: 6760 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE:
@@ -7373,6 +7326,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7373 public void llCloseRemoteDataChannel(string channel) 7326 public void llCloseRemoteDataChannel(string channel)
7374 { 7327 {
7375 m_host.AddScriptLPS(1); 7328 m_host.AddScriptLPS(1);
7329
7330 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
7331 if (xmlRpcRouter != null)
7332 {
7333 xmlRpcRouter.UnRegisterReceiver(channel, m_item.ItemID);
7334 }
7335
7376 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7336 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7377 if (xmlrpcMod != null) 7337 if (xmlrpcMod != null)
7378 xmlrpcMod.CloseXMLRPCChannel((UUID)channel); 7338 xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
@@ -7746,9 +7706,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7746 UUID sculptId; 7706 UUID sculptId;
7747 7707
7748 if (!UUID.TryParse(map, out sculptId)) 7708 if (!UUID.TryParse(map, out sculptId))
7749 { 7709 sculptId = ScriptUtils.GetAssetIdFromItemName(m_host, map, (int)AssetType.Texture);
7750 sculptId = InventoryKey(map, (int)AssetType.Texture);
7751 }
7752 7710
7753 if (sculptId == UUID.Zero) 7711 if (sculptId == UUID.Zero)
7754 return; 7712 return;
@@ -11519,6 +11477,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11519 case ScriptBaseClass.OBJECT_PHYSICS_COST: 11477 case ScriptBaseClass.OBJECT_PHYSICS_COST:
11520 ret.Add(new LSL_Float(0)); 11478 ret.Add(new LSL_Float(0));
11521 break; 11479 break;
11480 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
11481 ret.Add(new LSL_Float(0));
11482 break;
11483 case ScriptBaseClass.OBJECT_ROOT:
11484 SceneObjectPart p = av.ParentPart;
11485 if (p != null)
11486 {
11487 ret.Add(new LSL_String(p.ParentGroup.RootPart.UUID.ToString()));
11488 }
11489 else
11490 {
11491 ret.Add(new LSL_String(id));
11492 }
11493 break;
11494 case ScriptBaseClass.OBJECT_ATTACHED_POINT:
11495 ret.Add(new LSL_Integer(0));
11496 break;
11497 case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: // Pathfinding
11498 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_AVATAR));
11499 break;
11500 case ScriptBaseClass.OBJECT_PHYSICS:
11501 ret.Add(new LSL_Integer(0));
11502 break;
11503 case ScriptBaseClass.OBJECT_PHANTOM:
11504 ret.Add(new LSL_Integer(0));
11505 break;
11506 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
11507 ret.Add(new LSL_Integer(0));
11508 break;
11522 default: 11509 default:
11523 // Invalid or unhandled constant. 11510 // Invalid or unhandled constant.
11524 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 11511 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -11610,6 +11597,52 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11610 // The value returned in SL for normal prims is prim count 11597 // The value returned in SL for normal prims is prim count
11611 ret.Add(new LSL_Float(obj.PhysicsCost)); 11598 ret.Add(new LSL_Float(obj.PhysicsCost));
11612 break; 11599 break;
11600 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
11601 ret.Add(new LSL_Float(0));
11602 break;
11603 case ScriptBaseClass.OBJECT_ROOT:
11604 ret.Add(new LSL_String(obj.ParentGroup.RootPart.UUID.ToString()));
11605 break;
11606 case ScriptBaseClass.OBJECT_ATTACHED_POINT:
11607 ret.Add(new LSL_Integer(obj.ParentGroup.AttachmentPoint));
11608 break;
11609 case ScriptBaseClass.OBJECT_PATHFINDING_TYPE:
11610 byte pcode = obj.Shape.PCode;
11611 if (obj.ParentGroup.AttachmentPoint != 0
11612 || pcode == (byte)PCode.Grass
11613 || pcode == (byte)PCode.Tree
11614 || pcode == (byte)PCode.NewTree)
11615 {
11616 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_OTHER));
11617 }
11618 else
11619 {
11620 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_LEGACY_LINKSET));
11621 }
11622 break;
11623 case ScriptBaseClass.OBJECT_PHYSICS:
11624 if (obj.ParentGroup.AttachmentPoint != 0)
11625 {
11626 ret.Add(new LSL_Integer(0)); // Always false if attached
11627 }
11628 else
11629 {
11630 ret.Add(new LSL_Integer(obj.ParentGroup.UsesPhysics ? 1 : 0));
11631 }
11632 break;
11633 case ScriptBaseClass.OBJECT_PHANTOM:
11634 if (obj.ParentGroup.AttachmentPoint != 0)
11635 {
11636 ret.Add(new LSL_Integer(0)); // Always false if attached
11637 }
11638 else
11639 {
11640 ret.Add(new LSL_Integer(obj.ParentGroup.IsPhantom ? 1 : 0));
11641 }
11642 break;
11643 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
11644 ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0));
11645 break;
11613 default: 11646 default:
11614 // Invalid or unhandled constant. 11647 // Invalid or unhandled constant.
11615 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 11648 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -11993,12 +12026,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11993 radius = Math.Abs(maxY); 12026 radius = Math.Abs(maxY);
11994 if (Math.Abs(maxZ) > radius) 12027 if (Math.Abs(maxZ) > radius)
11995 radius = Math.Abs(maxZ); 12028 radius = Math.Abs(maxZ);
11996 12029 radius = radius*1.413f;
11997 Vector3 ac = group.AbsolutePosition - rayStart; 12030 Vector3 ac = group.AbsolutePosition - rayStart;
11998 Vector3 bc = group.AbsolutePosition - rayEnd; 12031 Vector3 bc = group.AbsolutePosition - rayEnd;
11999 12032
12000 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); 12033 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
12001 12034
12002 // Too far off ray, don't bother 12035 // Too far off ray, don't bother
12003 if (d > radius) 12036 if (d > radius)
12004 return; 12037 return;
@@ -12008,11 +12041,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12008 if (d2 > 0) 12041 if (d2 > 0)
12009 return; 12042 return;
12010 12043
12044 ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
12011 EntityIntersection intersection = group.TestIntersection(ray, true, false); 12045 EntityIntersection intersection = group.TestIntersection(ray, true, false);
12012 // Miss. 12046 // Miss.
12013 if (!intersection.HitTF) 12047 if (!intersection.HitTF)
12014 return; 12048 return;
12015 12049
12050 Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ);
12051 Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ);
12052 //m_log.DebugFormat("[LLCASTRAY]: min<{0},{1},{2}>, max<{3},{4},{5}> = hitp<{6},{7},{8}>", b1.X,b1.Y,b1.Z,b2.X,b2.Y,b2.Z,intersection.ipoint.X,intersection.ipoint.Y,intersection.ipoint.Z);
12053 if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X &&
12054 intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y &&
12055 intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z))
12056 return;
12057
12016 ContactResult result = new ContactResult (); 12058 ContactResult result = new ContactResult ();
12017 result.ConsumerID = group.LocalId; 12059 result.ConsumerID = group.LocalId;
12018// result.Depth = intersection.distance; 12060// result.Depth = intersection.distance;
@@ -12228,7 +12270,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12228 if (checkNonPhysical) 12270 if (checkNonPhysical)
12229 rayfilter |= RayFilterFlags.nonphysical; 12271 rayfilter |= RayFilterFlags.nonphysical;
12230 if (detectPhantom) 12272 if (detectPhantom)
12231 rayfilter |= RayFilterFlags.LSLPhanton; 12273 rayfilter |= RayFilterFlags.LSLPhantom;
12232 12274
12233 Vector3 direction = dir * ( 1/dist); 12275 Vector3 direction = dir * ( 1/dist);
12234 12276
@@ -12286,8 +12328,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12286 if (checkPhysical || checkNonPhysical || detectPhantom) 12328 if (checkPhysical || checkNonPhysical || detectPhantom)
12287 { 12329 {
12288 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); 12330 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
12289 foreach (ContactResult r in objectHits) 12331 for (int iter = 0; iter < objectHits.Length; iter++)
12290 results.Add(r); 12332 {
12333 // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler.
12334 objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart);
12335 results.Add(objectHits[iter]);
12336 }
12291 } 12337 }
12292 } 12338 }
12293 12339
@@ -13273,7 +13319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13273 /// Get a notecard line. 13319 /// Get a notecard line.
13274 /// </summary> 13320 /// </summary>
13275 /// <param name="assetID"></param> 13321 /// <param name="assetID"></param>
13276 /// <param name="line">Lines start at index 0</param> 13322 /// <param name="lineNumber">Lines start at index 0</param>
13277 /// <returns></returns> 13323 /// <returns></returns>
13278 public static string GetLine(UUID assetID, int lineNumber) 13324 public static string GetLine(UUID assetID, int lineNumber)
13279 { 13325 {
@@ -13302,9 +13348,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13302 /// Get a notecard line. 13348 /// Get a notecard line.
13303 /// </summary> 13349 /// </summary>
13304 /// <param name="assetID"></param> 13350 /// <param name="assetID"></param>
13305 /// <param name="line">Lines start at index 0</param> 13351 /// <param name="lineNumber">Lines start at index 0</param>
13306 /// <param name="maxLength">Maximum length of the returned line. Longer lines will be truncated</para> 13352 /// <param name="maxLength">
13307 /// <returns></returns> 13353 /// Maximum length of the returned line.
13354 /// </param>
13355 /// <returns>
13356 /// If the line length is longer than <paramref name="maxLength"/>,
13357 /// the return string will be truncated.
13358 /// </returns>
13308 public static string GetLine(UUID assetID, int lineNumber, int maxLength) 13359 public static string GetLine(UUID assetID, int lineNumber, int maxLength)
13309 { 13360 {
13310 string line = GetLine(assetID, lineNumber); 13361 string line = GetLine(assetID, lineNumber);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index ceb4660..1d6cb6d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -30,6 +30,7 @@ using System.Reflection;
30using System.Collections; 30using System.Collections;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
33using System.Threading;
33using OpenMetaverse; 34using OpenMetaverse;
34using Nini.Config; 35using Nini.Config;
35using OpenSim; 36using OpenSim;
@@ -61,9 +62,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
61 internal bool m_LSFunctionsEnabled = false; 62 internal bool m_LSFunctionsEnabled = false;
62 internal IScriptModuleComms m_comms = null; 63 internal IScriptModuleComms m_comms = null;
63 64
64 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 65 public void Initialize(
66 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
65 { 67 {
66 m_ScriptEngine = ScriptEngine; 68 m_ScriptEngine = scriptEngine;
67 m_host = host; 69 m_host = host;
68 70
69 if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) 71 if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false))
@@ -92,10 +94,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
92 get { return m_ScriptEngine.World; } 94 get { return m_ScriptEngine.World; }
93 } 95 }
94 96
95 // 97 /// <summary>
96 //Dumps an error message on the debug console. 98 /// Dumps an error message on the debug console.
97 // 99 /// </summary>
98
99 internal void LSShoutError(string message) 100 internal void LSShoutError(string message)
100 { 101 {
101 if (message.Length > 1023) 102 if (message.Length > 1023)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 8f34833..2fe6948 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -29,7 +29,10 @@ using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections; 30using System.Collections;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Reflection;
32using System.Runtime.Remoting.Lifetime; 33using System.Runtime.Remoting.Lifetime;
34using System.Threading;
35using log4net;
33using OpenMetaverse; 36using OpenMetaverse;
34using Nini.Config; 37using Nini.Config;
35using OpenSim; 38using OpenSim;
@@ -55,15 +58,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
55 [Serializable] 58 [Serializable]
56 public class MOD_Api : MarshalByRefObject, IMOD_Api, IScriptApi 59 public class MOD_Api : MarshalByRefObject, IMOD_Api, IScriptApi
57 { 60 {
61// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62
58 internal IScriptEngine m_ScriptEngine; 63 internal IScriptEngine m_ScriptEngine;
59 internal SceneObjectPart m_host; 64 internal SceneObjectPart m_host;
60 internal TaskInventoryItem m_item; 65 internal TaskInventoryItem m_item;
61 internal bool m_MODFunctionsEnabled = false; 66 internal bool m_MODFunctionsEnabled = false;
62 internal IScriptModuleComms m_comms = null; 67 internal IScriptModuleComms m_comms = null;
63 68
64 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 69 public void Initialize(
70 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
65 { 71 {
66 m_ScriptEngine = ScriptEngine; 72 m_ScriptEngine = scriptEngine;
67 m_host = host; 73 m_host = host;
68 m_item = item; 74 m_item = item;
69 75
@@ -107,8 +113,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
107 if (message.Length > 1023) 113 if (message.Length > 1023)
108 message = message.Substring(0, 1023); 114 message = message.Substring(0, 1023);
109 115
110 World.SimChat(Utils.StringToBytes(message), 116 World.SimChat(
111 ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); 117 Utils.StringToBytes(message),
118 ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL,
119 m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
112 120
113 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 121 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
114 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); 122 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
@@ -122,6 +130,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
122 /// <returns>string result of the invocation</returns> 130 /// <returns>string result of the invocation</returns>
123 public void modInvokeN(string fname, params object[] parms) 131 public void modInvokeN(string fname, params object[] parms)
124 { 132 {
133// m_log.DebugFormat(
134// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
135// fname,
136// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
137// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
138
125 Type returntype = m_comms.LookupReturnType(fname); 139 Type returntype = m_comms.LookupReturnType(fname);
126 if (returntype != typeof(string)) 140 if (returntype != typeof(string))
127 MODError(String.Format("return type mismatch for {0}",fname)); 141 MODError(String.Format("return type mismatch for {0}",fname));
@@ -131,6 +145,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
131 145
132 public LSL_String modInvokeS(string fname, params object[] parms) 146 public LSL_String modInvokeS(string fname, params object[] parms)
133 { 147 {
148// m_log.DebugFormat(
149// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
150// fname,
151// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
152// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
153
134 Type returntype = m_comms.LookupReturnType(fname); 154 Type returntype = m_comms.LookupReturnType(fname);
135 if (returntype != typeof(string)) 155 if (returntype != typeof(string))
136 MODError(String.Format("return type mismatch for {0}",fname)); 156 MODError(String.Format("return type mismatch for {0}",fname));
@@ -141,6 +161,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
141 161
142 public LSL_Integer modInvokeI(string fname, params object[] parms) 162 public LSL_Integer modInvokeI(string fname, params object[] parms)
143 { 163 {
164// m_log.DebugFormat(
165// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
166// fname,
167// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
168// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
169
144 Type returntype = m_comms.LookupReturnType(fname); 170 Type returntype = m_comms.LookupReturnType(fname);
145 if (returntype != typeof(int)) 171 if (returntype != typeof(int))
146 MODError(String.Format("return type mismatch for {0}",fname)); 172 MODError(String.Format("return type mismatch for {0}",fname));
@@ -151,6 +177,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
151 177
152 public LSL_Float modInvokeF(string fname, params object[] parms) 178 public LSL_Float modInvokeF(string fname, params object[] parms)
153 { 179 {
180// m_log.DebugFormat(
181// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
182// fname,
183// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
184// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
185
154 Type returntype = m_comms.LookupReturnType(fname); 186 Type returntype = m_comms.LookupReturnType(fname);
155 if (returntype != typeof(float)) 187 if (returntype != typeof(float))
156 MODError(String.Format("return type mismatch for {0}",fname)); 188 MODError(String.Format("return type mismatch for {0}",fname));
@@ -161,6 +193,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
161 193
162 public LSL_Key modInvokeK(string fname, params object[] parms) 194 public LSL_Key modInvokeK(string fname, params object[] parms)
163 { 195 {
196// m_log.DebugFormat(
197// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
198// fname,
199// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
200// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
201
164 Type returntype = m_comms.LookupReturnType(fname); 202 Type returntype = m_comms.LookupReturnType(fname);
165 if (returntype != typeof(UUID)) 203 if (returntype != typeof(UUID))
166 MODError(String.Format("return type mismatch for {0}",fname)); 204 MODError(String.Format("return type mismatch for {0}",fname));
@@ -171,6 +209,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
171 209
172 public LSL_Vector modInvokeV(string fname, params object[] parms) 210 public LSL_Vector modInvokeV(string fname, params object[] parms)
173 { 211 {
212// m_log.DebugFormat(
213// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
214// fname,
215// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
216// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
217
174 Type returntype = m_comms.LookupReturnType(fname); 218 Type returntype = m_comms.LookupReturnType(fname);
175 if (returntype != typeof(OpenMetaverse.Vector3)) 219 if (returntype != typeof(OpenMetaverse.Vector3))
176 MODError(String.Format("return type mismatch for {0}",fname)); 220 MODError(String.Format("return type mismatch for {0}",fname));
@@ -181,6 +225,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
181 225
182 public LSL_Rotation modInvokeR(string fname, params object[] parms) 226 public LSL_Rotation modInvokeR(string fname, params object[] parms)
183 { 227 {
228// m_log.DebugFormat(
229// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
230// fname,
231// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
232// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
233
184 Type returntype = m_comms.LookupReturnType(fname); 234 Type returntype = m_comms.LookupReturnType(fname);
185 if (returntype != typeof(OpenMetaverse.Quaternion)) 235 if (returntype != typeof(OpenMetaverse.Quaternion))
186 MODError(String.Format("return type mismatch for {0}",fname)); 236 MODError(String.Format("return type mismatch for {0}",fname));
@@ -191,6 +241,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
191 241
192 public LSL_List modInvokeL(string fname, params object[] parms) 242 public LSL_List modInvokeL(string fname, params object[] parms)
193 { 243 {
244// m_log.DebugFormat(
245// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
246// fname,
247// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
248// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
249
194 Type returntype = m_comms.LookupReturnType(fname); 250 Type returntype = m_comms.LookupReturnType(fname);
195 if (returntype != typeof(object[])) 251 if (returntype != typeof(object[]))
196 MODError(String.Format("return type mismatch for {0}",fname)); 252 MODError(String.Format("return type mismatch for {0}",fname));
@@ -248,6 +304,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
248 return ""; 304 return "";
249 } 305 }
250 306
307// m_log.DebugFormat(
308// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
309// fname,
310// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
311// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
312
251 Type[] signature = m_comms.LookupTypeSignature(fname); 313 Type[] signature = m_comms.LookupTypeSignature(fname);
252 if (signature.Length != parms.Length) 314 if (signature.Length != parms.Length)
253 MODError(String.Format("wrong number of parameters to function {0}",fname)); 315 MODError(String.Format("wrong number of parameters to function {0}",fname));
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 7c2f8ed..6ff6b00 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -143,9 +143,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
143 143
144 protected IUrlModule m_UrlModule = null; 144 protected IUrlModule m_UrlModule = null;
145 145
146 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 146 public void Initialize(
147 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
147 { 148 {
148 m_ScriptEngine = ScriptEngine; 149 m_ScriptEngine = scriptEngine;
149 m_host = host; 150 m_host = host;
150 m_item = item; 151 m_item = item;
151 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 152 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
@@ -254,11 +255,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
254 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); 255 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
255 } 256 }
256 257
258 // Returns of the function is allowed. Throws a script exception if not allowed.
257 public void CheckThreatLevel(ThreatLevel level, string function) 259 public void CheckThreatLevel(ThreatLevel level, string function)
258 { 260 {
259 if (!m_OSFunctionsEnabled) 261 if (!m_OSFunctionsEnabled)
260 OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws 262 OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws
261 263
264 string reasonWhyNot = CheckThreatLevelTest(level, function);
265 if (!String.IsNullOrEmpty(reasonWhyNot))
266 {
267 OSSLError(reasonWhyNot);
268 }
269 }
270
271 // Check to see if function is allowed. Returns an empty string if function permitted
272 // or a string explaining why this function can't be used.
273 private string CheckThreatLevelTest(ThreatLevel level, string function)
274 {
262 if (!m_FunctionPerms.ContainsKey(function)) 275 if (!m_FunctionPerms.ContainsKey(function))
263 { 276 {
264 FunctionPerms perms = new FunctionPerms(); 277 FunctionPerms perms = new FunctionPerms();
@@ -338,10 +351,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
338 { 351 {
339 // Allow / disallow by threat level 352 // Allow / disallow by threat level
340 if (level > m_MaxThreatLevel) 353 if (level > m_MaxThreatLevel)
341 OSSLError( 354 return
342 String.Format( 355 String.Format(
343 "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.", 356 "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.",
344 function, m_MaxThreatLevel, level)); 357 function, m_MaxThreatLevel, level);
345 } 358 }
346 else 359 else
347 { 360 {
@@ -351,7 +364,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
351 if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID)) 364 if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID))
352 { 365 {
353 // prim owner is in the list of allowed owners 366 // prim owner is in the list of allowed owners
354 return; 367 return String.Empty;
355 } 368 }
356 369
357 UUID ownerID = m_item.OwnerID; 370 UUID ownerID = m_item.OwnerID;
@@ -363,7 +376,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
363 376
364 if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero) 377 if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero)
365 { 378 {
366 return; 379 return String.Empty;
367 } 380 }
368 } 381 }
369 382
@@ -374,7 +387,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
374 387
375 if (land.LandData.OwnerID == ownerID) 388 if (land.LandData.OwnerID == ownerID)
376 { 389 {
377 return; 390 return String.Empty;
378 } 391 }
379 } 392 }
380 393
@@ -384,7 +397,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
384 //Only Estate Managers may use the function 397 //Only Estate Managers may use the function
385 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID) 398 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID)
386 { 399 {
387 return; 400 return String.Empty;
388 } 401 }
389 } 402 }
390 403
@@ -393,25 +406,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
393 { 406 {
394 if (World.RegionInfo.EstateSettings.EstateOwner == ownerID) 407 if (World.RegionInfo.EstateSettings.EstateOwner == ownerID)
395 { 408 {
396 return; 409 return String.Empty;
397 } 410 }
398 } 411 }
399 412
400 if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID)) 413 if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID))
401 OSSLError( 414 return(
402 String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.", 415 String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.",
403 function)); 416 function));
404 417
405 if (m_item.CreatorID != ownerID) 418 if (m_item.CreatorID != ownerID)
406 { 419 {
407 if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0) 420 if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0)
408 OSSLError( 421 return String.Format("{0} permission denied. Script permissions error.", function);
409 String.Format("{0} permission denied. Script permissions error.",
410 function));
411 422
412 } 423 }
413 } 424 }
414 } 425 }
426 return String.Empty;
415 } 427 }
416 428
417 internal void OSSLDeprecated(string function, string replacement) 429 internal void OSSLDeprecated(string function, string replacement)
@@ -983,7 +995,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
983 if (animID == UUID.Zero) 995 if (animID == UUID.Zero)
984 target.Animator.RemoveAnimation(animation); 996 target.Animator.RemoveAnimation(animation);
985 else 997 else
986 target.Animator.RemoveAnimation(animID); 998 target.Animator.RemoveAnimation(animID, true);
987 } 999 }
988 } 1000 }
989 } 1001 }
@@ -1214,12 +1226,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1214 sunHour += 24.0; 1226 sunHour += 24.0;
1215 1227
1216 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun; 1228 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun;
1217 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30 1229 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30
1218 World.RegionInfo.RegionSettings.FixedSun = sunFixed; 1230 World.RegionInfo.RegionSettings.FixedSun = sunFixed;
1219 World.RegionInfo.RegionSettings.Save(); 1231 World.RegionInfo.RegionSettings.Save();
1220 1232
1221 World.EventManager.TriggerEstateToolsSunUpdate( 1233 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle);
1222 World.RegionInfo.RegionHandle, sunFixed, useEstateSun, (float)sunHour);
1223 } 1234 }
1224 1235
1225 /// <summary> 1236 /// <summary>
@@ -1244,8 +1255,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1244 World.RegionInfo.EstateSettings.FixedSun = sunFixed; 1255 World.RegionInfo.EstateSettings.FixedSun = sunFixed;
1245 World.RegionInfo.EstateSettings.Save(); 1256 World.RegionInfo.EstateSettings.Save();
1246 1257
1247 World.EventManager.TriggerEstateToolsSunUpdate( 1258 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle);
1248 World.RegionInfo.RegionHandle, sunFixed, World.RegionInfo.RegionSettings.UseEstateSun, (float)sunHour);
1249 } 1259 }
1250 1260
1251 /// <summary> 1261 /// <summary>
@@ -1569,6 +1579,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1569 } 1579 }
1570 } 1580 }
1571 1581
1582 public string osGetPhysicsEngineType()
1583 {
1584 // High because it can be used to target attacks to known weaknesses
1585 // This would allow a new class of griefer scripts that don't even
1586 // require their user to know what they are doing (see script
1587 // kiddie)
1588 // Because it would be nice if scripts didn't blow up if the information
1589 // about the physics engine, this function returns an empty string if
1590 // the user does not have permission to see it. This as opposed to
1591 // throwing an exception.
1592 m_host.AddScriptLPS(1);
1593 string ret = String.Empty;
1594 if (String.IsNullOrEmpty(CheckThreatLevelTest(ThreatLevel.High, "osGetPhysicsEngineType")))
1595 {
1596 if (m_ScriptEngine.World.PhysicsScene != null)
1597 {
1598 ret = m_ScriptEngine.World.PhysicsScene.EngineType;
1599 // An old physics engine might have an uninitialized engine type
1600 if (ret == null)
1601 ret = "unknown";
1602 }
1603 }
1604
1605 return ret;
1606 }
1607
1572 public string osGetSimulatorVersion() 1608 public string osGetSimulatorVersion()
1573 { 1609 {
1574 // High because it can be used to target attacks to known weaknesses 1610 // High because it can be used to target attacks to known weaknesses
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 4dd795d..d3ef378 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -42,6 +42,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
42 { 42 {
43// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 43// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 44
45 /// <summary>
46 /// Used by one-off and repeated sensors
47 /// </summary>
48 public class SensorInfo
49 {
50 public uint localID;
51 public UUID itemID;
52 public double interval;
53 public DateTime next;
54
55 public string name;
56 public UUID keyID;
57 public int type;
58 public double range;
59 public double arc;
60 public SceneObjectPart host;
61
62 public SensorInfo Clone()
63 {
64 return (SensorInfo)this.MemberwiseClone();
65 }
66 }
67
45 public AsyncCommandManager m_CmdManager; 68 public AsyncCommandManager m_CmdManager;
46 69
47 /// <summary> 70 /// <summary>
@@ -78,24 +101,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
78 private int maximumToReturn = 16; 101 private int maximumToReturn = 16;
79 102
80 // 103 //
81 // SenseRepeater and Sensors
82 //
83 private class SenseRepeatClass
84 {
85 public uint localID;
86 public UUID itemID;
87 public double interval;
88 public DateTime next;
89
90 public string name;
91 public UUID keyID;
92 public int type;
93 public double range;
94 public double arc;
95 public SceneObjectPart host;
96 }
97
98 //
99 // Sensed entity 104 // Sensed entity
100 // 105 //
101 private class SensedEntity : IComparable 106 private class SensedEntity : IComparable
@@ -127,7 +132,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
127 /// 132 ///
128 /// Always lock SenseRepeatListLock when updating this list. 133 /// Always lock SenseRepeatListLock when updating this list.
129 /// </remarks> 134 /// </remarks>
130 private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>(); 135 private List<SensorInfo> SenseRepeaters = new List<SensorInfo>();
131 private object SenseRepeatListLock = new object(); 136 private object SenseRepeatListLock = new object();
132 137
133 public void SetSenseRepeatEvent(uint m_localID, UUID m_itemID, 138 public void SetSenseRepeatEvent(uint m_localID, UUID m_itemID,
@@ -141,7 +146,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
141 return; 146 return;
142 147
143 // Add to timer 148 // Add to timer
144 SenseRepeatClass ts = new SenseRepeatClass(); 149 SensorInfo ts = new SensorInfo();
145 ts.localID = m_localID; 150 ts.localID = m_localID;
146 ts.itemID = m_itemID; 151 ts.itemID = m_itemID;
147 ts.interval = sec; 152 ts.interval = sec;
@@ -160,11 +165,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
160 AddSenseRepeater(ts); 165 AddSenseRepeater(ts);
161 } 166 }
162 167
163 private void AddSenseRepeater(SenseRepeatClass senseRepeater) 168 private void AddSenseRepeater(SensorInfo senseRepeater)
164 { 169 {
165 lock (SenseRepeatListLock) 170 lock (SenseRepeatListLock)
166 { 171 {
167 List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>(SenseRepeaters); 172 List<SensorInfo> newSenseRepeaters = new List<SensorInfo>(SenseRepeaters);
168 newSenseRepeaters.Add(senseRepeater); 173 newSenseRepeaters.Add(senseRepeater);
169 SenseRepeaters = newSenseRepeaters; 174 SenseRepeaters = newSenseRepeaters;
170 } 175 }
@@ -175,8 +180,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
175 // Remove from timer 180 // Remove from timer
176 lock (SenseRepeatListLock) 181 lock (SenseRepeatListLock)
177 { 182 {
178 List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>(); 183 List<SensorInfo> newSenseRepeaters = new List<SensorInfo>();
179 foreach (SenseRepeatClass ts in SenseRepeaters) 184 foreach (SensorInfo ts in SenseRepeaters)
180 { 185 {
181 if (ts.localID != m_localID || ts.itemID != m_itemID) 186 if (ts.localID != m_localID || ts.itemID != m_itemID)
182 { 187 {
@@ -191,7 +196,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
191 public void CheckSenseRepeaterEvents() 196 public void CheckSenseRepeaterEvents()
192 { 197 {
193 // Go through all timers 198 // Go through all timers
194 foreach (SenseRepeatClass ts in SenseRepeaters) 199 foreach (SensorInfo ts in SenseRepeaters)
195 { 200 {
196 // Time has passed? 201 // Time has passed?
197 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) 202 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
@@ -208,7 +213,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
208 double range, double arc, SceneObjectPart host) 213 double range, double arc, SceneObjectPart host)
209 { 214 {
210 // Add to timer 215 // Add to timer
211 SenseRepeatClass ts = new SenseRepeatClass(); 216 SensorInfo ts = new SensorInfo();
212 ts.localID = m_localID; 217 ts.localID = m_localID;
213 ts.itemID = m_itemID; 218 ts.itemID = m_itemID;
214 ts.interval = 0; 219 ts.interval = 0;
@@ -224,7 +229,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
224 SensorSweep(ts); 229 SensorSweep(ts);
225 } 230 }
226 231
227 private void SensorSweep(SenseRepeatClass ts) 232 private void SensorSweep(SensorInfo ts)
228 { 233 {
229 if (ts.host == null) 234 if (ts.host == null)
230 { 235 {
@@ -300,7 +305,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
300 } 305 }
301 } 306 }
302 307
303 private List<SensedEntity> doObjectSensor(SenseRepeatClass ts) 308 private List<SensedEntity> doObjectSensor(SensorInfo ts)
304 { 309 {
305 List<EntityBase> Entities; 310 List<EntityBase> Entities;
306 List<SensedEntity> sensedEntities = new List<SensedEntity>(); 311 List<SensedEntity> sensedEntities = new List<SensedEntity>();
@@ -451,7 +456,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
451 return sensedEntities; 456 return sensedEntities;
452 } 457 }
453 458
454 private List<SensedEntity> doAgentSensor(SenseRepeatClass ts) 459 private List<SensedEntity> doAgentSensor(SensorInfo ts)
455 { 460 {
456 List<SensedEntity> sensedEntities = new List<SensedEntity>(); 461 List<SensedEntity> sensedEntities = new List<SensedEntity>();
457 462
@@ -630,7 +635,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
630 { 635 {
631 List<Object> data = new List<Object>(); 636 List<Object> data = new List<Object>();
632 637
633 foreach (SenseRepeatClass ts in SenseRepeaters) 638 foreach (SensorInfo ts in SenseRepeaters)
634 { 639 {
635 if (ts.itemID == itemID) 640 if (ts.itemID == itemID)
636 { 641 {
@@ -660,7 +665,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
660 665
661 while (idx < data.Length) 666 while (idx < data.Length)
662 { 667 {
663 SenseRepeatClass ts = new SenseRepeatClass(); 668 SensorInfo ts = new SensorInfo();
664 669
665 ts.localID = localID; 670 ts.localID = localID;
666 ts.itemID = itemID; 671 ts.itemID = itemID;
@@ -681,5 +686,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
681 idx += 6; 686 idx += 6;
682 } 687 }
683 } 688 }
689
690 public List<SensorInfo> GetSensorInfo()
691 {
692 List<SensorInfo> retList = new List<SensorInfo>();
693
694 lock (SenseRepeatListLock)
695 {
696 foreach (SensorInfo i in SenseRepeaters)
697 retList.Add(i.Clone());
698 }
699
700 return retList;
701 }
684 } 702 }
685} 703} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
index 9ee6946..68aacd2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
@@ -35,6 +35,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
35{ 35{
36 public class Timer 36 public class Timer
37 { 37 {
38 public class TimerInfo
39 {
40 public uint localID;
41 public UUID itemID;
42 //public double interval;
43 public long interval;
44 //public DateTime next;
45 public long next;
46
47 public TimerInfo Clone()
48 {
49 return (TimerInfo)this.MemberwiseClone();
50 }
51 }
52
38 public AsyncCommandManager m_CmdManager; 53 public AsyncCommandManager m_CmdManager;
39 54
40 public int TimersCount 55 public int TimersCount
@@ -59,17 +74,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
59 return localID.ToString() + itemID.ToString(); 74 return localID.ToString() + itemID.ToString();
60 } 75 }
61 76
62 private class TimerClass 77 private Dictionary<string,TimerInfo> Timers = new Dictionary<string,TimerInfo>();
63 {
64 public uint localID;
65 public UUID itemID;
66 //public double interval;
67 public long interval;
68 //public DateTime next;
69 public long next;
70 }
71
72 private Dictionary<string,TimerClass> Timers = new Dictionary<string,TimerClass>();
73 private object TimerListLock = new object(); 78 private object TimerListLock = new object();
74 79
75 public void SetTimerEvent(uint m_localID, UUID m_itemID, double sec) 80 public void SetTimerEvent(uint m_localID, UUID m_itemID, double sec)
@@ -81,7 +86,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
81 } 86 }
82 87
83 // Add to timer 88 // Add to timer
84 TimerClass ts = new TimerClass(); 89 TimerInfo ts = new TimerInfo();
85 ts.localID = m_localID; 90 ts.localID = m_localID;
86 ts.itemID = m_itemID; 91 ts.itemID = m_itemID;
87 ts.interval = Convert.ToInt64(sec * 10000000); // How many 100 nanoseconds (ticks) should we wait 92 ts.interval = Convert.ToInt64(sec * 10000000); // How many 100 nanoseconds (ticks) should we wait
@@ -118,14 +123,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
118 if (Timers.Count == 0) 123 if (Timers.Count == 0)
119 return; 124 return;
120 125
121 Dictionary<string, TimerClass>.ValueCollection tvals; 126 Dictionary<string, TimerInfo>.ValueCollection tvals;
122 lock (TimerListLock) 127 lock (TimerListLock)
123 { 128 {
124 // Go through all timers 129 // Go through all timers
125 tvals = Timers.Values; 130 tvals = Timers.Values;
126 } 131 }
127 132
128 foreach (TimerClass ts in tvals) 133 foreach (TimerInfo ts in tvals)
129 { 134 {
130 // Time has passed? 135 // Time has passed?
131 if (ts.next < DateTime.Now.Ticks) 136 if (ts.next < DateTime.Now.Ticks)
@@ -149,8 +154,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
149 154
150 lock (TimerListLock) 155 lock (TimerListLock)
151 { 156 {
152 Dictionary<string, TimerClass>.ValueCollection tvals = Timers.Values; 157 Dictionary<string, TimerInfo>.ValueCollection tvals = Timers.Values;
153 foreach (TimerClass ts in tvals) 158 foreach (TimerInfo ts in tvals)
154 { 159 {
155 if (ts.itemID == itemID) 160 if (ts.itemID == itemID)
156 { 161 {
@@ -169,7 +174,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
169 174
170 while (idx < data.Length) 175 while (idx < data.Length)
171 { 176 {
172 TimerClass ts = new TimerClass(); 177 TimerInfo ts = new TimerInfo();
173 178
174 ts.localID = localID; 179 ts.localID = localID;
175 ts.itemID = itemID; 180 ts.itemID = itemID;
@@ -183,5 +188,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
183 } 188 }
184 } 189 }
185 } 190 }
191
192 public List<TimerInfo> GetTimersInfo()
193 {
194 List<TimerInfo> retList = new List<TimerInfo>();
195
196 lock (TimerListLock)
197 {
198 foreach (TimerInfo i in Timers.Values)
199 retList.Add(i.Clone());
200 }
201
202 return retList;
203 }
186 } 204 }
187} 205}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
index d173db0..3c01eec 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index c447d1f..7eb347e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -259,6 +259,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
259 259
260 string osGetScriptEngineName(); 260 string osGetScriptEngineName();
261 string osGetSimulatorVersion(); 261 string osGetSimulatorVersion();
262 string osGetPhysicsEngineType();
262 Object osParseJSONNew(string JSON); 263 Object osParseJSONNew(string JSON);
263 Hashtable osParseJSON(string JSON); 264 Hashtable osParseJSON(string JSON);
264 265
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 0dd5a57..da3b31f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -557,6 +557,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
557 public const int OBJECT_SERVER_COST = 14; 557 public const int OBJECT_SERVER_COST = 14;
558 public const int OBJECT_STREAMING_COST = 15; 558 public const int OBJECT_STREAMING_COST = 15;
559 public const int OBJECT_PHYSICS_COST = 16; 559 public const int OBJECT_PHYSICS_COST = 16;
560 public const int OBJECT_CHARACTER_TIME = 17;
561 public const int OBJECT_ROOT = 18;
562 public const int OBJECT_ATTACHED_POINT = 19;
563 public const int OBJECT_PATHFINDING_TYPE = 20;
564 public const int OBJECT_PHYSICS = 21;
565 public const int OBJECT_PHANTOM = 22;
566 public const int OBJECT_TEMP_ON_REZ = 23;
567
568 // Pathfinding types
569 public const int OPT_OTHER = -1;
570 public const int OPT_LEGACY_LINKSET = 0;
571 public const int OPT_AVATAR = 1;
572 public const int OPT_CHARACTER = 2;
573 public const int OPT_WALKABLE = 3;
574 public const int OPT_STATIC_OBSTACLE = 4;
575 public const int OPT_MATERIAL_VOLUME = 5;
576 public const int OPT_EXCLUSION_VOLUME = 6;
560 577
561 // for llGetAgentList 578 // for llGetAgentList
562 public const int AGENT_LIST_PARCEL = 1; 579 public const int AGENT_LIST_PARCEL = 1;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index afa9ae0..c9902e4 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -420,6 +420,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
420 return m_OSSL_Functions.osGetScriptEngineName(); 420 return m_OSSL_Functions.osGetScriptEngineName();
421 } 421 }
422 422
423 public string osGetPhysicsEngineType()
424 {
425 return m_OSSL_Functions.osGetPhysicsEngineType();
426 }
427
423 public string osGetSimulatorVersion() 428 public string osGetSimulatorVersion()
424 { 429 {
425 return m_OSSL_Functions.osGetSimulatorVersion(); 430 return m_OSSL_Functions.osGetSimulatorVersion();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs
index 573a803..b1825ac 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs
index f6d5d41..342dbff 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
index 97dd0f6..9e32f40 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using log4net; 32using log4net;
33using Tools; 33using Tools;
34
35using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
36 35
37namespace OpenSim.Region.ScriptEngine.Shared.CodeTools 36namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
@@ -49,6 +48,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
49 private List<string> m_warnings = new List<string>(); 48 private List<string> m_warnings = new List<string>();
50 private IScriptModuleComms m_comms = null; 49 private IScriptModuleComms m_comms = null;
51 50
51 private bool m_insertCoopTerminationChecks;
52 private static string m_coopTerminationCheck = "opensim_reserved_CheckForCoopTermination();";
53
54 /// <summary>
55 /// Keep a record of the previous node when we do the parsing.
56 /// </summary>
57 /// <remarks>
58 /// We do this here because the parser generated by CSTools does not retain a reference to its parent node.
59 /// The previous node is required so we can correctly insert co-op termination checks when required.
60 /// </remarks>
61// private SYMBOL m_previousNode;
62
52 /// <summary> 63 /// <summary>
53 /// Creates an 'empty' CSCodeGenerator instance. 64 /// Creates an 'empty' CSCodeGenerator instance.
54 /// </summary> 65 /// </summary>
@@ -58,9 +69,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
58 ResetCounters(); 69 ResetCounters();
59 } 70 }
60 71
61 public CSCodeGenerator(IScriptModuleComms comms) 72 public CSCodeGenerator(IScriptModuleComms comms, bool insertCoopTerminationChecks)
62 { 73 {
63 m_comms = comms; 74 m_comms = comms;
75 m_insertCoopTerminationChecks = insertCoopTerminationChecks;
64 ResetCounters(); 76 ResetCounters();
65 } 77 }
66 78
@@ -155,7 +167,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
155 // here's the payload 167 // here's the payload
156 retstr += GenerateLine(); 168 retstr += GenerateLine();
157 foreach (SYMBOL s in m_astRoot.kids) 169 foreach (SYMBOL s in m_astRoot.kids)
158 retstr += GenerateNode(s); 170 retstr += GenerateNode(m_astRoot, s);
159 171
160 // close braces! 172 // close braces!
161 m_braceCount--; 173 m_braceCount--;
@@ -165,7 +177,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
165 177
166 // Removes all carriage return characters which may be generated in Windows platform. Is there 178 // Removes all carriage return characters which may be generated in Windows platform. Is there
167 // cleaner way of doing this? 179 // cleaner way of doing this?
168 retstr=retstr.Replace("\r", ""); 180 retstr = retstr.Replace("\r", "");
169 181
170 return retstr; 182 return retstr;
171 } 183 }
@@ -191,9 +203,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
191 /// Recursively called to generate each type of node. Will generate this 203 /// Recursively called to generate each type of node. Will generate this
192 /// node, then all it's children. 204 /// node, then all it's children.
193 /// </summary> 205 /// </summary>
206 /// <param name="previousSymbol">The parent node.</param>
194 /// <param name="s">The current node to generate code for.</param> 207 /// <param name="s">The current node to generate code for.</param>
195 /// <returns>String containing C# code for SYMBOL s.</returns> 208 /// <returns>String containing C# code for SYMBOL s.</returns>
196 private string GenerateNode(SYMBOL s) 209 private string GenerateNode(SYMBOL previousSymbol, SYMBOL s)
197 { 210 {
198 string retstr = String.Empty; 211 string retstr = String.Empty;
199 212
@@ -207,11 +220,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
207 else if (s is State) 220 else if (s is State)
208 retstr += GenerateState((State) s); 221 retstr += GenerateState((State) s);
209 else if (s is CompoundStatement) 222 else if (s is CompoundStatement)
210 retstr += GenerateCompoundStatement((CompoundStatement) s); 223 retstr += GenerateCompoundStatement(previousSymbol, (CompoundStatement) s);
211 else if (s is Declaration) 224 else if (s is Declaration)
212 retstr += GenerateDeclaration((Declaration) s); 225 retstr += GenerateDeclaration((Declaration) s);
213 else if (s is Statement) 226 else if (s is Statement)
214 retstr += GenerateStatement((Statement) s); 227 retstr += GenerateStatement(previousSymbol, (Statement) s);
215 else if (s is ReturnStatement) 228 else if (s is ReturnStatement)
216 retstr += GenerateReturnStatement((ReturnStatement) s); 229 retstr += GenerateReturnStatement((ReturnStatement) s);
217 else if (s is JumpLabel) 230 else if (s is JumpLabel)
@@ -261,7 +274,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
261 else 274 else
262 { 275 {
263 foreach (SYMBOL kid in s.kids) 276 foreach (SYMBOL kid in s.kids)
264 retstr += GenerateNode(kid); 277 retstr += GenerateNode(s, kid);
265 } 278 }
266 279
267 return retstr; 280 return retstr;
@@ -295,7 +308,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
295 retstr += GenerateLine(")"); 308 retstr += GenerateLine(")");
296 309
297 foreach (SYMBOL kid in remainingKids) 310 foreach (SYMBOL kid in remainingKids)
298 retstr += GenerateNode(kid); 311 retstr += GenerateNode(gf, kid);
299 312
300 return retstr; 313 return retstr;
301 } 314 }
@@ -312,7 +325,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
312 foreach (SYMBOL s in gv.kids) 325 foreach (SYMBOL s in gv.kids)
313 { 326 {
314 retstr += Indent(); 327 retstr += Indent();
315 retstr += GenerateNode(s); 328 retstr += GenerateNode(gv, s);
316 retstr += GenerateLine(";"); 329 retstr += GenerateLine(";");
317 } 330 }
318 331
@@ -365,7 +378,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
365 retstr += GenerateLine(")"); 378 retstr += GenerateLine(")");
366 379
367 foreach (SYMBOL kid in remainingKids) 380 foreach (SYMBOL kid in remainingKids)
368 retstr += GenerateNode(kid); 381 retstr += GenerateNode(se, kid);
369 382
370 return retstr; 383 return retstr;
371 } 384 }
@@ -404,7 +417,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
404 417
405 foreach (SYMBOL s in al.kids) 418 foreach (SYMBOL s in al.kids)
406 { 419 {
407 retstr += GenerateNode(s); 420 retstr += GenerateNode(al, s);
408 if (0 < comma--) 421 if (0 < comma--)
409 retstr += Generate(", "); 422 retstr += Generate(", ");
410 } 423 }
@@ -417,7 +430,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
417 /// </summary> 430 /// </summary>
418 /// <param name="cs">The CompoundStatement node.</param> 431 /// <param name="cs">The CompoundStatement node.</param>
419 /// <returns>String containing C# code for CompoundStatement cs.</returns> 432 /// <returns>String containing C# code for CompoundStatement cs.</returns>
420 private string GenerateCompoundStatement(CompoundStatement cs) 433 private string GenerateCompoundStatement(SYMBOL previousSymbol, CompoundStatement cs)
421 { 434 {
422 string retstr = String.Empty; 435 string retstr = String.Empty;
423 436
@@ -425,8 +438,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
425 retstr += GenerateIndentedLine("{"); 438 retstr += GenerateIndentedLine("{");
426 m_braceCount++; 439 m_braceCount++;
427 440
441 if (m_insertCoopTerminationChecks)
442 {
443 // We have to check in event functions as well because the user can manually call these.
444 if (previousSymbol is GlobalFunctionDefinition
445 || previousSymbol is WhileStatement
446 || previousSymbol is DoWhileStatement
447 || previousSymbol is ForLoop
448 || previousSymbol is StateEvent)
449 retstr += GenerateIndentedLine(m_coopTerminationCheck);
450 }
451
428 foreach (SYMBOL kid in cs.kids) 452 foreach (SYMBOL kid in cs.kids)
429 retstr += GenerateNode(kid); 453 retstr += GenerateNode(cs, kid);
430 454
431 // closing brace 455 // closing brace
432 m_braceCount--; 456 m_braceCount--;
@@ -450,10 +474,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
450 /// </summary> 474 /// </summary>
451 /// <param name="s">The Statement node.</param> 475 /// <param name="s">The Statement node.</param>
452 /// <returns>String containing C# code for Statement s.</returns> 476 /// <returns>String containing C# code for Statement s.</returns>
453 private string GenerateStatement(Statement s) 477 private string GenerateStatement(SYMBOL previousSymbol, Statement s)
454 { 478 {
455 string retstr = String.Empty; 479 string retstr = String.Empty;
456 bool printSemicolon = true; 480 bool printSemicolon = true;
481 bool transformToBlock = false;
482
483 if (m_insertCoopTerminationChecks)
484 {
485 // A non-braced single line do while structure cannot contain multiple statements.
486 // So to insert the termination check we change this to a braced control structure instead.
487 if (previousSymbol is WhileStatement
488 || previousSymbol is DoWhileStatement
489 || previousSymbol is ForLoop)
490 {
491 transformToBlock = true;
492
493 // FIXME: This will be wrongly indented because the previous for/while/dowhile will have already indented.
494 retstr += GenerateIndentedLine("{");
495
496 retstr += GenerateIndentedLine(m_coopTerminationCheck);
497 }
498 }
457 499
458 retstr += Indent(); 500 retstr += Indent();
459 501
@@ -466,12 +508,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
466 // (MONO) error. 508 // (MONO) error.
467 if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count)) 509 if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count))
468 foreach (SYMBOL kid in s.kids) 510 foreach (SYMBOL kid in s.kids)
469 retstr += GenerateNode(kid); 511 retstr += GenerateNode(s, kid);
470 } 512 }
471 513
472 if (printSemicolon) 514 if (printSemicolon)
473 retstr += GenerateLine(";"); 515 retstr += GenerateLine(";");
474 516
517 if (transformToBlock)
518 {
519 // FIXME: This will be wrongly indented because the for/while/dowhile is currently handling the unindent
520 retstr += GenerateIndentedLine("}");
521 }
522
475 return retstr; 523 return retstr;
476 } 524 }
477 525
@@ -487,10 +535,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
487 List<string> identifiers = new List<string>(); 535 List<string> identifiers = new List<string>();
488 checkForMultipleAssignments(identifiers, a); 536 checkForMultipleAssignments(identifiers, a);
489 537
490 retstr += GenerateNode((SYMBOL) a.kids.Pop()); 538 retstr += GenerateNode(a, (SYMBOL) a.kids.Pop());
491 retstr += Generate(String.Format(" {0} ", a.AssignmentType), a); 539 retstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
492 foreach (SYMBOL kid in a.kids) 540 foreach (SYMBOL kid in a.kids)
493 retstr += GenerateNode(kid); 541 retstr += GenerateNode(a, kid);
494 542
495 return retstr; 543 return retstr;
496 } 544 }
@@ -563,7 +611,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
563 retstr += Generate("return ", rs); 611 retstr += Generate("return ", rs);
564 612
565 foreach (SYMBOL kid in rs.kids) 613 foreach (SYMBOL kid in rs.kids)
566 retstr += GenerateNode(kid); 614 retstr += GenerateNode(rs, kid);
567 615
568 return retstr; 616 return retstr;
569 } 617 }
@@ -575,7 +623,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
575 /// <returns>String containing C# code for JumpLabel jl.</returns> 623 /// <returns>String containing C# code for JumpLabel jl.</returns>
576 private string GenerateJumpLabel(JumpLabel jl) 624 private string GenerateJumpLabel(JumpLabel jl)
577 { 625 {
578 return Generate(String.Format("{0}:", CheckName(jl.LabelName)), jl) + " NoOp();\n"; 626 string labelStatement;
627
628 if (m_insertCoopTerminationChecks)
629 labelStatement = m_coopTerminationCheck + "\n";
630 else
631 labelStatement = "NoOp();\n";
632
633 return Generate(String.Format("{0}: ", CheckName(jl.LabelName)), jl) + labelStatement;
579 } 634 }
580 635
581 /// <summary> 636 /// <summary>
@@ -598,14 +653,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
598 string retstr = String.Empty; 653 string retstr = String.Empty;
599 654
600 retstr += GenerateIndented("if (", ifs); 655 retstr += GenerateIndented("if (", ifs);
601 retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); 656 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
602 retstr += GenerateLine(")"); 657 retstr += GenerateLine(")");
603 658
604 // CompoundStatement handles indentation itself but we need to do it 659 // CompoundStatement handles indentation itself but we need to do it
605 // otherwise. 660 // otherwise.
606 bool indentHere = ifs.kids.Top is Statement; 661 bool indentHere = ifs.kids.Top is Statement;
607 if (indentHere) m_braceCount++; 662 if (indentHere) m_braceCount++;
608 retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); 663 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
609 if (indentHere) m_braceCount--; 664 if (indentHere) m_braceCount--;
610 665
611 if (0 < ifs.kids.Count) // do it again for an else 666 if (0 < ifs.kids.Count) // do it again for an else
@@ -614,7 +669,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
614 669
615 indentHere = ifs.kids.Top is Statement; 670 indentHere = ifs.kids.Top is Statement;
616 if (indentHere) m_braceCount++; 671 if (indentHere) m_braceCount++;
617 retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); 672 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
618 if (indentHere) m_braceCount--; 673 if (indentHere) m_braceCount--;
619 } 674 }
620 675
@@ -641,14 +696,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
641 string retstr = String.Empty; 696 string retstr = String.Empty;
642 697
643 retstr += GenerateIndented("while (", ws); 698 retstr += GenerateIndented("while (", ws);
644 retstr += GenerateNode((SYMBOL) ws.kids.Pop()); 699 retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
645 retstr += GenerateLine(")"); 700 retstr += GenerateLine(")");
646 701
647 // CompoundStatement handles indentation itself but we need to do it 702 // CompoundStatement handles indentation itself but we need to do it
648 // otherwise. 703 // otherwise.
649 bool indentHere = ws.kids.Top is Statement; 704 bool indentHere = ws.kids.Top is Statement;
650 if (indentHere) m_braceCount++; 705 if (indentHere) m_braceCount++;
651 retstr += GenerateNode((SYMBOL) ws.kids.Pop()); 706 retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
652 if (indentHere) m_braceCount--; 707 if (indentHere) m_braceCount--;
653 708
654 return retstr; 709 return retstr;
@@ -669,11 +724,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
669 // otherwise. 724 // otherwise.
670 bool indentHere = dws.kids.Top is Statement; 725 bool indentHere = dws.kids.Top is Statement;
671 if (indentHere) m_braceCount++; 726 if (indentHere) m_braceCount++;
672 retstr += GenerateNode((SYMBOL) dws.kids.Pop()); 727 retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
673 if (indentHere) m_braceCount--; 728 if (indentHere) m_braceCount--;
674 729
675 retstr += GenerateIndented("while (", dws); 730 retstr += GenerateIndented("while (", dws);
676 retstr += GenerateNode((SYMBOL) dws.kids.Pop()); 731 retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
677 retstr += GenerateLine(");"); 732 retstr += GenerateLine(");");
678 733
679 return retstr; 734 return retstr;
@@ -702,7 +757,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
702 retstr += Generate("; "); 757 retstr += Generate("; ");
703 // for (x = 0; x < 10; x++) 758 // for (x = 0; x < 10; x++)
704 // ^^^^^^ 759 // ^^^^^^
705 retstr += GenerateNode((SYMBOL) fl.kids.Pop()); 760 retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
706 retstr += Generate("; "); 761 retstr += Generate("; ");
707 // for (x = 0; x < 10; x++) 762 // for (x = 0; x < 10; x++)
708 // ^^^ 763 // ^^^
@@ -713,7 +768,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
713 // otherwise. 768 // otherwise.
714 bool indentHere = fl.kids.Top is Statement; 769 bool indentHere = fl.kids.Top is Statement;
715 if (indentHere) m_braceCount++; 770 if (indentHere) m_braceCount++;
716 retstr += GenerateNode((SYMBOL) fl.kids.Pop()); 771 retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
717 if (indentHere) m_braceCount--; 772 if (indentHere) m_braceCount--;
718 773
719 return retstr; 774 return retstr;
@@ -758,7 +813,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
758 while (s is ParenthesisExpression) 813 while (s is ParenthesisExpression)
759 s = (SYMBOL)s.kids.Pop(); 814 s = (SYMBOL)s.kids.Pop();
760 815
761 retstr += GenerateNode(s); 816 retstr += GenerateNode(fls, s);
762 if (0 < comma--) 817 if (0 < comma--)
763 retstr += Generate(", "); 818 retstr += Generate(", ");
764 } 819 }
@@ -779,20 +834,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
779 { 834 {
780 // special case handling for logical and/or, see Mantis 3174 835 // special case handling for logical and/or, see Mantis 3174
781 retstr += "((bool)("; 836 retstr += "((bool)(";
782 retstr += GenerateNode((SYMBOL)be.kids.Pop()); 837 retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
783 retstr += "))"; 838 retstr += "))";
784 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0,1)), be); 839 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0,1)), be);
785 retstr += "((bool)("; 840 retstr += "((bool)(";
786 foreach (SYMBOL kid in be.kids) 841 foreach (SYMBOL kid in be.kids)
787 retstr += GenerateNode(kid); 842 retstr += GenerateNode(be, kid);
788 retstr += "))"; 843 retstr += "))";
789 } 844 }
790 else 845 else
791 { 846 {
792 retstr += GenerateNode((SYMBOL)be.kids.Pop()); 847 retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
793 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be); 848 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
794 foreach (SYMBOL kid in be.kids) 849 foreach (SYMBOL kid in be.kids)
795 retstr += GenerateNode(kid); 850 retstr += GenerateNode(be, kid);
796 } 851 }
797 852
798 return retstr; 853 return retstr;
@@ -808,7 +863,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
808 string retstr = String.Empty; 863 string retstr = String.Empty;
809 864
810 retstr += Generate(ue.UnarySymbol, ue); 865 retstr += Generate(ue.UnarySymbol, ue);
811 retstr += GenerateNode((SYMBOL) ue.kids.Pop()); 866 retstr += GenerateNode(ue, (SYMBOL) ue.kids.Pop());
812 867
813 return retstr; 868 return retstr;
814 } 869 }
@@ -824,7 +879,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
824 879
825 retstr += Generate("("); 880 retstr += Generate("(");
826 foreach (SYMBOL kid in pe.kids) 881 foreach (SYMBOL kid in pe.kids)
827 retstr += GenerateNode(kid); 882 retstr += GenerateNode(pe, kid);
828 retstr += Generate(")"); 883 retstr += Generate(")");
829 884
830 return retstr; 885 return retstr;
@@ -861,7 +916,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
861 916
862 // we wrap all typecasted statements in parentheses 917 // we wrap all typecasted statements in parentheses
863 retstr += Generate(String.Format("({0}) (", te.TypecastType), te); 918 retstr += Generate(String.Format("({0}) (", te.TypecastType), te);
864 retstr += GenerateNode((SYMBOL) te.kids.Pop()); 919 retstr += GenerateNode(te, (SYMBOL) te.kids.Pop());
865 retstr += Generate(")"); 920 retstr += Generate(")");
866 921
867 return retstr; 922 return retstr;
@@ -931,7 +986,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
931 } 986 }
932 987
933 foreach (SYMBOL kid in fc.kids) 988 foreach (SYMBOL kid in fc.kids)
934 retstr += GenerateNode(kid); 989 retstr += GenerateNode(fc, kid);
935 990
936 retstr += Generate(")"); 991 retstr += Generate(")");
937 992
@@ -980,11 +1035,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
980 string retstr = String.Empty; 1035 string retstr = String.Empty;
981 1036
982 retstr += Generate(String.Format("new {0}(", vc.Type), vc); 1037 retstr += Generate(String.Format("new {0}(", vc.Type), vc);
983 retstr += GenerateNode((SYMBOL) vc.kids.Pop()); 1038 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
984 retstr += Generate(", "); 1039 retstr += Generate(", ");
985 retstr += GenerateNode((SYMBOL) vc.kids.Pop()); 1040 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
986 retstr += Generate(", "); 1041 retstr += Generate(", ");
987 retstr += GenerateNode((SYMBOL) vc.kids.Pop()); 1042 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
988 retstr += Generate(")"); 1043 retstr += Generate(")");
989 1044
990 return retstr; 1045 return retstr;
@@ -1000,13 +1055,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
1000 string retstr = String.Empty; 1055 string retstr = String.Empty;
1001 1056
1002 retstr += Generate(String.Format("new {0}(", rc.Type), rc); 1057 retstr += Generate(String.Format("new {0}(", rc.Type), rc);
1003 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1058 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1004 retstr += Generate(", "); 1059 retstr += Generate(", ");
1005 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1060 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1006 retstr += Generate(", "); 1061 retstr += Generate(", ");
1007 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1062 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1008 retstr += Generate(", "); 1063 retstr += Generate(", ");
1009 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1064 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1010 retstr += Generate(")"); 1065 retstr += Generate(")");
1011 1066
1012 return retstr; 1067 return retstr;
@@ -1024,7 +1079,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
1024 retstr += Generate(String.Format("new {0}(", lc.Type), lc); 1079 retstr += Generate(String.Format("new {0}(", lc.Type), lc);
1025 1080
1026 foreach (SYMBOL kid in lc.kids) 1081 foreach (SYMBOL kid in lc.kids)
1027 retstr += GenerateNode(kid); 1082 retstr += GenerateNode(lc, kid);
1028 1083
1029 retstr += Generate(")"); 1084 retstr += Generate(")");
1030 1085
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 03be2ab..9d20c9e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -72,6 +72,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
72 private bool CompileWithDebugInformation; 72 private bool CompileWithDebugInformation;
73 private Dictionary<string, bool> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase); 73 private Dictionary<string, bool> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
74 private Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase); 74 private Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase);
75 private bool m_insertCoopTerminationCalls;
75 76
76 private string FilePrefix; 77 private string FilePrefix;
77 private string ScriptEnginesPath = null; 78 private string ScriptEnginesPath = null;
@@ -95,20 +96,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
95 private Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>> m_lineMaps = 96 private Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>> m_lineMaps =
96 new Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>>(); 97 new Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>>();
97 98
99 public bool in_startup = true;
100
98 public Compiler(IScriptEngine scriptEngine) 101 public Compiler(IScriptEngine scriptEngine)
99 { 102 {
100 m_scriptEngine = scriptEngine;; 103 m_scriptEngine = scriptEngine;
101 ScriptEnginesPath = scriptEngine.ScriptEnginePath; 104 ScriptEnginesPath = scriptEngine.ScriptEnginePath;
102 ReadConfig(); 105 ReadConfig();
103 } 106 }
104 107
105 public bool in_startup = true;
106 public void ReadConfig() 108 public void ReadConfig()
107 { 109 {
108 // Get some config 110 // Get some config
109 WriteScriptSourceToDebugFile = m_scriptEngine.Config.GetBoolean("WriteScriptSourceToDebugFile", false); 111 WriteScriptSourceToDebugFile = m_scriptEngine.Config.GetBoolean("WriteScriptSourceToDebugFile", false);
110 CompileWithDebugInformation = m_scriptEngine.Config.GetBoolean("CompileWithDebugInformation", true); 112 CompileWithDebugInformation = m_scriptEngine.Config.GetBoolean("CompileWithDebugInformation", true);
111 bool DeleteScriptsOnStartup = m_scriptEngine.Config.GetBoolean("DeleteScriptsOnStartup", true); 113 bool DeleteScriptsOnStartup = m_scriptEngine.Config.GetBoolean("DeleteScriptsOnStartup", true);
114 m_insertCoopTerminationCalls = m_scriptEngine.Config.GetString("ScriptStopStrategy", "abort") == "co-op";
112 115
113 // Get file prefix from scriptengine name and make it file system safe: 116 // Get file prefix from scriptengine name and make it file system safe:
114 FilePrefix = "CommonCompiler"; 117 FilePrefix = "CommonCompiler";
@@ -386,7 +389,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
386 if (language == enumCompileType.lsl) 389 if (language == enumCompileType.lsl)
387 { 390 {
388 // Its LSL, convert it to C# 391 // Its LSL, convert it to C#
389 LSL_Converter = (ICodeConverter)new CSCodeGenerator(comms); 392 LSL_Converter = (ICodeConverter)new CSCodeGenerator(comms, m_insertCoopTerminationCalls);
390 compileScript = LSL_Converter.Convert(Script); 393 compileScript = LSL_Converter.Convert(Script);
391 394
392 // copy converter warnings into our warnings. 395 // copy converter warnings into our warnings.
@@ -411,16 +414,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
411 { 414 {
412 case enumCompileType.cs: 415 case enumCompileType.cs:
413 case enumCompileType.lsl: 416 case enumCompileType.lsl:
414 compileScript = CreateCSCompilerScript(compileScript); 417 compileScript = CreateCSCompilerScript(
418 compileScript,
419 m_scriptEngine.ScriptClassName,
420 m_scriptEngine.ScriptBaseClassName,
421 m_scriptEngine.ScriptBaseClassParameters);
415 break; 422 break;
416 case enumCompileType.vb: 423 case enumCompileType.vb:
417 compileScript = CreateVBCompilerScript(compileScript); 424 compileScript = CreateVBCompilerScript(
425 compileScript, m_scriptEngine.ScriptClassName, m_scriptEngine.ScriptBaseClassName);
418 break; 426 break;
419// case enumCompileType.js: 427// case enumCompileType.js:
420// compileScript = CreateJSCompilerScript(compileScript); 428// compileScript = CreateJSCompilerScript(compileScript, m_scriptEngine.ScriptBaseClassName);
421// break; 429// break;
422 case enumCompileType.yp: 430 case enumCompileType.yp:
423 compileScript = CreateYPCompilerScript(compileScript); 431 compileScript = CreateYPCompilerScript(
432 compileScript, m_scriptEngine.ScriptClassName,m_scriptEngine.ScriptBaseClassName);
424 break; 433 break;
425 } 434 }
426 435
@@ -451,43 +460,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
451// return compileScript; 460// return compileScript;
452// } 461// }
453 462
454 private static string CreateCSCompilerScript(string compileScript) 463 private static string CreateCSCompilerScript(
464 string compileScript, string className, string baseClassName, ParameterInfo[] constructorParameters)
455 { 465 {
456 compileScript = String.Empty + 466 compileScript = string.Format(
457 "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" + 467@"using OpenSim.Region.ScriptEngine.Shared;
458 String.Empty + "namespace SecondLife { " + 468using System.Collections.Generic;
459 String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" + 469
460 @"public Script() { } " + 470namespace SecondLife
461 compileScript + 471{{
462 "} }\r\n"; 472 public class {0} : {1}
473 {{
474 public {0}({2}) : base({3}) {{}}
475{4}
476 }}
477}}",
478 className,
479 baseClassName,
480 constructorParameters != null
481 ? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.ToString()))
482 : "",
483 constructorParameters != null
484 ? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.Name))
485 : "",
486 compileScript);
487
463 return compileScript; 488 return compileScript;
464 } 489 }
465 490
466 private static string CreateYPCompilerScript(string compileScript) 491 private static string CreateYPCompilerScript(string compileScript, string className, string baseClassName)
467 { 492 {
468 compileScript = String.Empty + 493 compileScript = String.Empty +
469 "using OpenSim.Region.ScriptEngine.Shared.YieldProlog; " + 494 "using OpenSim.Region.ScriptEngine.Shared.YieldProlog; " +
470 "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" + 495 "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" +
471 String.Empty + "namespace SecondLife { " + 496 String.Empty + "namespace SecondLife { " +
472 String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" + 497 String.Empty + "public class " + className + " : " + baseClassName + " { \r\n" +
473 //@"public Script() { } " + 498 //@"public Script() { } " +
474 @"static OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP YP=null; " + 499 @"static OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP YP=null; " +
475 @"public Script() { YP= new OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP(); } " + 500 @"public " + className + "() { YP= new OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP(); } " +
476
477 compileScript + 501 compileScript +
478 "} }\r\n"; 502 "} }\r\n";
503
479 return compileScript; 504 return compileScript;
480 } 505 }
481 506
482 private static string CreateVBCompilerScript(string compileScript) 507 private static string CreateVBCompilerScript(string compileScript, string className, string baseClassName)
483 { 508 {
484 compileScript = String.Empty + 509 compileScript = String.Empty +
485 "Imports OpenSim.Region.ScriptEngine.Shared: Imports System.Collections.Generic: " + 510 "Imports OpenSim.Region.ScriptEngine.Shared: Imports System.Collections.Generic: " +
486 String.Empty + "NameSpace SecondLife:" + 511 String.Empty + "NameSpace SecondLife:" +
487 String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass: " + 512 String.Empty + "Public Class " + className + ": Inherits " + baseClassName +
488 "\r\nPublic Sub New()\r\nEnd Sub: " + 513 "\r\nPublic Sub New()\r\nEnd Sub: " +
489 compileScript + 514 compileScript +
490 ":End Class :End Namespace\r\n"; 515 ":End Class :End Namespace\r\n";
516
491 return compileScript; 517 return compileScript;
492 } 518 }
493 519
@@ -549,6 +575,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
549 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, 575 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
550 "OpenMetaverseTypes.dll")); 576 "OpenMetaverseTypes.dll"));
551 577
578 if (m_scriptEngine.ScriptReferencedAssemblies != null)
579 Array.ForEach<string>(
580 m_scriptEngine.ScriptReferencedAssemblies,
581 a => parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, a)));
582
552 if (lang == enumCompileType.yp) 583 if (lang == enumCompileType.yp)
553 { 584 {
554 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, 585 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
index c65caa8..fd37753 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
index 7763619..77e087c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
39 /// The generated C# code is compared against the expected C# code. 39 /// The generated C# code is compared against the expected C# code.
40 /// </summary> 40 /// </summary>
41 [TestFixture] 41 [TestFixture]
42 public class CSCodeGeneratorTest 42 public class CSCodeGeneratorTest : OpenSimTestCase
43 { 43 {
44 [Test] 44 [Test]
45 public void TestDefaultState() 45 public void TestDefaultState()
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
index 1fa6954..05a8756 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
41 /// the LSL source. 41 /// the LSL source.
42 /// </summary> 42 /// </summary>
43 [TestFixture] 43 [TestFixture]
44 public class CompilerTest 44 public class CompilerTest : OpenSimTestCase
45 { 45 {
46 private string m_testDir; 46 private string m_testDir;
47 private CSharpCodeProvider m_CSCodeProvider; 47 private CSharpCodeProvider m_CSCodeProvider;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 22804f5..e44a106 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -82,6 +82,24 @@ namespace OpenSim.Region.ScriptEngine.Shared
82 } 82 }
83 } 83 }
84 84
85 /// <summary>
86 /// Used to signal when the script is stopping in co-operation with the script engine
87 /// (instead of through Thread.Abort()).
88 /// </summary>
89 [Serializable]
90 public class ScriptCoopStopException : Exception
91 {
92 public ScriptCoopStopException()
93 {
94 }
95
96 protected ScriptCoopStopException(
97 SerializationInfo info,
98 StreamingContext context)
99 {
100 }
101 }
102
85 public class DetectParams 103 public class DetectParams
86 { 104 {
87 public const int AGENT = 1; 105 public const int AGENT = 1;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
index 470e1a1..74747a2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 771db0c..c8ced43 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -94,6 +94,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
94 private UUID m_CurrentStateHash; 94 private UUID m_CurrentStateHash;
95 private UUID m_RegionID; 95 private UUID m_RegionID;
96 96
97 public int DebugLevel { get; set; }
98
97 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; } 99 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; }
98 100
99 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); 101 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
@@ -156,6 +158,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
156 158
157 public UUID AppDomain { get; set; } 159 public UUID AppDomain { get; set; }
158 160
161 public SceneObjectPart Part { get; private set; }
162
159 public string PrimName { get; private set; } 163 public string PrimName { get; private set; }
160 164
161 public string ScriptName { get; private set; } 165 public string ScriptName { get; private set; }
@@ -174,6 +178,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
174 178
175 public Queue EventQueue { get; private set; } 179 public Queue EventQueue { get; private set; }
176 180
181 public long EventsQueued
182 {
183 get
184 {
185 lock (EventQueue)
186 return EventQueue.Count;
187 }
188 }
189
190 public long EventsProcessed { get; private set; }
191
177 public int StartParam { get; set; } 192 public int StartParam { get; set; }
178 193
179 public TaskInventoryItem ScriptTask { get; private set; } 194 public TaskInventoryItem ScriptTask { get; private set; }
@@ -186,66 +201,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
186 201
187 public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute; 202 public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute;
188 203
204 private bool m_coopTermination;
205
206 private EventWaitHandle m_coopSleepHandle;
207
189 public void ClearQueue() 208 public void ClearQueue()
190 { 209 {
191 m_TimerQueued = false; 210 m_TimerQueued = false;
192 EventQueue.Clear(); 211 EventQueue.Clear();
193 } 212 }
194 213
195 public ScriptInstance(IScriptEngine engine, SceneObjectPart part, 214 public ScriptInstance(
196 UUID itemID, UUID assetID, string assembly, 215 IScriptEngine engine, SceneObjectPart part, TaskInventoryItem item,
197 AppDomain dom, string primName, string scriptName, 216 int startParam, bool postOnRez,
198 int startParam, bool postOnRez, StateSource stateSource, 217 int maxScriptQueue)
199 int maxScriptQueue)
200 { 218 {
201 State = "default"; 219 State = "default";
202 EventQueue = new Queue(32); 220 EventQueue = new Queue(32);
203 221
204 Engine = engine; 222 Engine = engine;
205 LocalID = part.LocalId; 223 Part = part;
206 ObjectID = part.UUID; 224 ScriptTask = item;
207 RootLocalID = part.ParentGroup.LocalId; 225
208 RootObjectID = part.ParentGroup.UUID; 226 // This is currently only here to allow regression tests to get away without specifying any inventory
209 ItemID = itemID; 227 // item when they are testing script logic that doesn't require an item.
210 AssetID = assetID; 228 if (ScriptTask != null)
211 PrimName = primName; 229 {
212 ScriptName = scriptName; 230 ScriptName = ScriptTask.Name;
213 m_Assembly = assembly; 231 ItemID = ScriptTask.ItemID;
232 AssetID = ScriptTask.AssetID;
233 }
234
235 PrimName = part.ParentGroup.Name;
214 StartParam = startParam; 236 StartParam = startParam;
215 m_MaxScriptQueue = maxScriptQueue; 237 m_MaxScriptQueue = maxScriptQueue;
216 m_stateSource = stateSource;
217 m_postOnRez = postOnRez; 238 m_postOnRez = postOnRez;
218 m_AttachedAvatar = part.ParentGroup.AttachedAvatar; 239 m_AttachedAvatar = part.ParentGroup.AttachedAvatar;
219 m_RegionID = part.ParentGroup.Scene.RegionInfo.RegionID; 240 m_RegionID = part.ParentGroup.Scene.RegionInfo.RegionID;
220 241
221 if (part != null) 242 if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op")
222 { 243 {
223 part.TaskInventory.LockItemsForRead(true); 244 m_coopTermination = true;
224 if (part.TaskInventory.ContainsKey(ItemID)) 245 m_coopSleepHandle = new AutoResetEvent(false);
225 {
226 ScriptTask = part.TaskInventory[ItemID];
227 }
228 part.TaskInventory.LockItemsForRead(false);
229 } 246 }
247 }
248
249 /// <summary>
250 /// Load the script from an assembly into an AppDomain.
251 /// </summary>
252 /// <param name='dom'></param>
253 /// <param name='assembly'></param>
254 /// <param name='stateSource'></param>
255 /// <returns>false if load failed, true if suceeded</returns>
256 public bool Load(AppDomain dom, string assembly, StateSource stateSource)
257 {
258 m_Assembly = assembly;
259 m_stateSource = stateSource;
230 260
231 ApiManager am = new ApiManager(); 261 ApiManager am = new ApiManager();
232 262
233 foreach (string api in am.GetApis()) 263 foreach (string api in am.GetApis())
234 { 264 {
235 m_Apis[api] = am.CreateApi(api); 265 m_Apis[api] = am.CreateApi(api);
236 m_Apis[api].Initialize(engine, part, ScriptTask); 266 m_Apis[api].Initialize(Engine, Part, ScriptTask, m_coopSleepHandle);
237 } 267 }
238 268
239 try 269 try
240 { 270 {
271 object[] constructorParams;
272
273 Assembly scriptAssembly = dom.Load(Path.GetFileNameWithoutExtension(assembly));
274 Type scriptType = scriptAssembly.GetType("SecondLife.XEngineScript");
275
276 if (scriptType != null)
277 {
278 constructorParams = new object[] { m_coopSleepHandle };
279 }
280 else if (!m_coopTermination)
281 {
282 scriptType = scriptAssembly.GetType("SecondLife.Script");
283 constructorParams = null;
284 }
285 else
286 {
287 m_log.ErrorFormat(
288 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. You must remove all existing {6}* script DLL files before using enabling co-op termination"
289 + ", either by setting DeleteScriptsOnStartup = true in [XEngine] for one run"
290 + " or by deleting these files manually.",
291 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly);
292
293 return false;
294 }
295
296// m_log.DebugFormat(
297// "[SCRIPT INSTANCE]: Looking to load {0} from assembly {1} in {2}",
298// scriptType.FullName, Path.GetFileNameWithoutExtension(assembly), Engine.World.Name);
299
241 if (dom != System.AppDomain.CurrentDomain) 300 if (dom != System.AppDomain.CurrentDomain)
242 m_Script = (IScript)dom.CreateInstanceAndUnwrap( 301 m_Script
302 = (IScript)dom.CreateInstanceAndUnwrap(
243 Path.GetFileNameWithoutExtension(assembly), 303 Path.GetFileNameWithoutExtension(assembly),
244 "SecondLife.Script"); 304 scriptType.FullName,
305 false,
306 BindingFlags.Default,
307 null,
308 constructorParams,
309 null,
310 null,
311 null);
245 else 312 else
246 m_Script = (IScript)Assembly.Load( 313 m_Script
247 Path.GetFileNameWithoutExtension(assembly)).CreateInstance( 314 = (IScript)scriptAssembly.CreateInstance(
248 "SecondLife.Script"); 315 scriptType.FullName,
316 false,
317 BindingFlags.Default,
318 null,
319 constructorParams,
320 null,
321 null);
249 322
250 //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); 323 //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
251 //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); 324 //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
@@ -254,8 +327,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
254 catch (Exception e) 327 catch (Exception e)
255 { 328 {
256 m_log.ErrorFormat( 329 m_log.ErrorFormat(
257 "[SCRIPT INSTANCE]: Error loading assembly {0}. Exception {1}{2}", 330 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error loading assembly {6}. Exception {7}{8}",
258 assembly, e.Message, e.StackTrace); 331 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly, e.Message, e.StackTrace);
332
333 return false;
259 } 334 }
260 335
261 try 336 try
@@ -267,16 +342,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
267 342
268// // m_log.Debug("[Script] Script instance created"); 343// // m_log.Debug("[Script] Script instance created");
269 344
270 part.SetScriptEvents(ItemID, 345 Part.SetScriptEvents(ItemID,
271 (int)m_Script.GetStateEventFlags(State)); 346 (int)m_Script.GetStateEventFlags(State));
272 } 347 }
273 catch (Exception e) 348 catch (Exception e)
274 { 349 {
275 m_log.ErrorFormat( 350 m_log.ErrorFormat(
276 "[SCRIPT INSTANCE]: Error loading script instance from assembly {0}. Exception {1}{2}", 351 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error initializing script instance. Exception {6}{7}",
277 assembly, e.Message, e.StackTrace); 352 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, e.Message, e.StackTrace);
278 353
279 return; 354 return false;
280 } 355 }
281 356
282 m_SaveState = true; 357 m_SaveState = true;
@@ -309,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
309 384
310// m_log.DebugFormat("[Script] Successfully retrieved state for script {0}.{1}", PrimName, m_ScriptName); 385// m_log.DebugFormat("[Script] Successfully retrieved state for script {0}.{1}", PrimName, m_ScriptName);
311 386
312 part.SetScriptEvents(ItemID, 387 Part.SetScriptEvents(ItemID,
313 (int)m_Script.GetStateEventFlags(State)); 388 (int)m_Script.GetStateEventFlags(State));
314 389
315 if (!Running) 390 if (!Running)
@@ -329,15 +404,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
329 else 404 else
330 { 405 {
331 m_log.WarnFormat( 406 m_log.WarnFormat(
332 "[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}). Memory limit exceeded", 407 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. Memory limit exceeded.",
333 savedState, ScriptName, ItemID, PrimName, ObjectID, assembly); 408 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState);
334 } 409 }
335 } 410 }
336 catch (Exception e) 411 catch (Exception e)
337 { 412 {
338 m_log.ErrorFormat( 413 m_log.ErrorFormat(
339 "[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}). XML is {6}. Exception {7}{8}", 414 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. XML is {7}. Exception {8}{9}",
340 savedState, ScriptName, ItemID, PrimName, ObjectID, assembly, xml, e.Message, e.StackTrace); 415 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState, xml, e.Message, e.StackTrace);
341 } 416 }
342 } 417 }
343// else 418// else
@@ -348,6 +423,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
348// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false); 423// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
349 424
350// } 425// }
426
427 return true;
351 } 428 }
352 429
353 public void Init() 430 public void Init()
@@ -521,9 +598,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
521 } 598 }
522 599
523 // Wait for the current event to complete. 600 // Wait for the current event to complete.
524 if (!m_InSelfDelete && workItem.Wait(new TimeSpan((long)timeout * 100000))) 601 if (!m_InSelfDelete)
525 { 602 {
526 return true; 603 if (!m_coopTermination)
604 {
605 // If we're not co-operative terminating then try and wait for the event to complete before stopping
606 if (workItem.Wait(new TimeSpan((long)timeout * 100000)))
607 return true;
608 }
609 else
610 {
611 if (DebugLevel >= 1)
612 m_log.DebugFormat(
613 "[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}",
614 ScriptName, ItemID, PrimName, ObjectID);
615
616 // This will terminate the event on next handle check by the script.
617 m_coopSleepHandle.Set();
618
619 // For now, we will wait forever since the event should always cleanly terminate once LSL loop
620 // checking is implemented. May want to allow a shorter timeout option later.
621 if (workItem.Wait(TimeSpan.MaxValue))
622 {
623 if (DebugLevel >= 1)
624 m_log.DebugFormat(
625 "[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}",
626 ScriptName, ItemID, PrimName, ObjectID);
627
628 return true;
629 }
630 }
527 } 631 }
528 632
529 lock (EventQueue) 633 lock (EventQueue)
@@ -536,11 +640,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
536 640
537 // If the event still hasn't stopped and we the stop isn't the result of script or object removal, then 641 // If the event still hasn't stopped and we the stop isn't the result of script or object removal, then
538 // forcibly abort the work item (this aborts the underlying thread). 642 // forcibly abort the work item (this aborts the underlying thread).
643 // Co-operative termination should never reach this point.
539 if (!m_InSelfDelete) 644 if (!m_InSelfDelete)
540 { 645 {
541// m_log.ErrorFormat( 646 m_log.DebugFormat(
542// "[SCRIPT INSTANCE]: Aborting script {0} {1} in prim {2} {3} {4} {5}", 647 "[SCRIPT INSTANCE]: Aborting unstopped script {0} {1} in prim {2}, localID {3}, timeout was {4} ms",
543// ScriptName, ItemID, PrimName, ObjectID, m_InSelfDelete, DateTime.Now.Ticks); 648 ScriptName, ItemID, PrimName, LocalID, timeout);
544 649
545 workItem.Abort(); 650 workItem.Abort();
546 } 651 }
@@ -696,19 +801,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
696 { 801 {
697 802
698// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this); 803// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this);
804 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
805
806 if (DebugLevel >= 2)
807 m_log.DebugFormat(
808 "[SCRIPT INSTANCE]: Processing event {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
809 data.EventName,
810 ScriptName,
811 part.Name,
812 part.LocalId,
813 part.ParentGroup.Name,
814 part.ParentGroup.UUID,
815 part.AbsolutePosition,
816 part.ParentGroup.Scene.Name);
699 817
700 m_DetectParams = data.DetectParams; 818 m_DetectParams = data.DetectParams;
701 819
702 if (data.EventName == "state") // Hardcoded state change 820 if (data.EventName == "state") // Hardcoded state change
703 { 821 {
704 // m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}",
705 // PrimName, ScriptName, data.Params[0].ToString());
706 State = data.Params[0].ToString(); 822 State = data.Params[0].ToString();
823
824 if (DebugLevel >= 1)
825 m_log.DebugFormat(
826 "[SCRIPT INSTANCE]: Changing state to {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
827 State,
828 ScriptName,
829 part.Name,
830 part.LocalId,
831 part.ParentGroup.Name,
832 part.ParentGroup.UUID,
833 part.AbsolutePosition,
834 part.ParentGroup.Scene.Name);
835
707 AsyncCommandManager.RemoveScript(Engine, 836 AsyncCommandManager.RemoveScript(Engine,
708 LocalID, ItemID); 837 LocalID, ItemID);
709 838
710 SceneObjectPart part = Engine.World.GetSceneObjectPart(
711 LocalID);
712 if (part != null) 839 if (part != null)
713 { 840 {
714 part.SetScriptEvents(ItemID, 841 part.SetScriptEvents(ItemID,
@@ -720,8 +847,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
720 if (Engine.World.PipeEventsForScript(LocalID) || 847 if (Engine.World.PipeEventsForScript(LocalID) ||
721 data.EventName == "control") // Don't freeze avies! 848 data.EventName == "control") // Don't freeze avies!
722 { 849 {
723 SceneObjectPart part = Engine.World.GetSceneObjectPart(
724 LocalID);
725 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", 850 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
726 // PrimName, ScriptName, data.EventName, State); 851 // PrimName, ScriptName, data.EventName, State);
727 852
@@ -763,7 +888,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
763 m_InEvent = false; 888 m_InEvent = false;
764 m_CurrentEvent = String.Empty; 889 m_CurrentEvent = String.Empty;
765 890
766 if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException)) 891 if ((!(e is TargetInvocationException)
892 || (!(e.InnerException is SelfDeleteException)
893 && !(e.InnerException is ScriptDeleteException)
894 && !(e.InnerException is ScriptCoopStopException)))
895 && !(e is ThreadAbortException))
767 { 896 {
768 try 897 try
769 { 898 {
@@ -776,6 +905,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
776 ChatTypeEnum.DebugChannel, 2147483647, 905 ChatTypeEnum.DebugChannel, 2147483647,
777 part.AbsolutePosition, 906 part.AbsolutePosition,
778 part.Name, part.UUID, false); 907 part.Name, part.UUID, false);
908
909
910 m_log.DebugFormat(
911 "[SCRIPT INSTANCE]: Runtime error in script {0}, part {1} {2} at {3} in {4}, displayed error {5}, actual exception {6}",
912 ScriptName,
913 PrimName,
914 part.UUID,
915 part.AbsolutePosition,
916 part.ParentGroup.Scene.Name,
917 text.Replace("\n", "\\n"),
918 e.InnerException);
779 } 919 }
780 catch (Exception) 920 catch (Exception)
781 { 921 {
@@ -802,6 +942,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
802 if (part != null) 942 if (part != null)
803 part.Inventory.RemoveInventoryItem(ItemID); 943 part.Inventory.RemoveInventoryItem(ItemID);
804 } 944 }
945 else if ((e is TargetInvocationException) && (e.InnerException is ScriptCoopStopException))
946 {
947 if (DebugLevel >= 1)
948 m_log.DebugFormat(
949 "[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.",
950 PrimName, ScriptName, data.EventName, State);
951 }
805 } 952 }
806 } 953 }
807 } 954 }
@@ -810,6 +957,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
810 // script engine to run the next event. 957 // script engine to run the next event.
811 lock (EventQueue) 958 lock (EventQueue)
812 { 959 {
960 EventsProcessed++;
961
813 if (EventQueue.Count > 0 && Running && !ShuttingDown) 962 if (EventQueue.Count > 0 && Running && !ShuttingDown)
814 { 963 {
815 m_CurrentWorkItem = Engine.QueueEventHandler(this); 964 m_CurrentWorkItem = Engine.QueueEventHandler(this);
@@ -834,7 +983,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
834 return (DateTime.Now - m_EventStart).Seconds; 983 return (DateTime.Now - m_EventStart).Seconds;
835 } 984 }
836 985
837 public void ResetScript() 986 public void ResetScript(int timeout)
838 { 987 {
839 if (m_Script == null) 988 if (m_Script == null)
840 return; 989 return;
@@ -844,7 +993,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
844 RemoveState(); 993 RemoveState();
845 ReleaseControls(); 994 ReleaseControls();
846 995
847 Stop(0); 996 Stop(timeout);
848 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); 997 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
849 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; 998 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0;
850 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero; 999 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
@@ -1015,7 +1164,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1015 "({0}): {1}", scriptLine - 1, 1164 "({0}): {1}", scriptLine - 1,
1016 e.InnerException.Message); 1165 e.InnerException.Message);
1017 1166
1018 System.Console.WriteLine(e.ToString()+"\n");
1019 return message; 1167 return message;
1020 } 1168 }
1021 } 1169 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
new file mode 100644
index 0000000..7ea30bf1
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
@@ -0,0 +1,514 @@
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.Threading;
31using Nini.Config;
32using NUnit.Framework;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.CoreModules.Scripting.WorldComm;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.ScriptEngine.XEngine;
39using OpenSim.Tests.Common;
40using OpenSim.Tests.Common.Mock;
41
42namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
43{
44 /// <summary>
45 /// Test that co-operative script thread termination is working correctly.
46 /// </summary>
47 [TestFixture]
48 public class CoopTerminationTests : OpenSimTestCase
49 {
50 private TestScene m_scene;
51 private OpenSim.Region.ScriptEngine.XEngine.XEngine m_xEngine;
52
53 private AutoResetEvent m_chatEvent;
54 private AutoResetEvent m_stoppedEvent;
55
56 private OSChatMessage m_osChatMessageReceived;
57
58 /// <summary>
59 /// Number of chat messages received so far. Reset before each test.
60 /// </summary>
61 private int m_chatMessagesReceived;
62
63 /// <summary>
64 /// Number of chat messages expected. m_chatEvent is not fired until this number is reached or exceeded.
65 /// </summary>
66 private int m_chatMessagesThreshold;
67
68 [SetUp]
69 public void Init()
70 {
71 m_osChatMessageReceived = null;
72 m_chatMessagesReceived = 0;
73 m_chatMessagesThreshold = 0;
74 m_chatEvent = new AutoResetEvent(false);
75 m_stoppedEvent = new AutoResetEvent(false);
76
77 //AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin");
78// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
79 m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine();
80
81 IniConfigSource configSource = new IniConfigSource();
82
83 IConfig startupConfig = configSource.AddConfig("Startup");
84 startupConfig.Set("DefaultScriptEngine", "XEngine");
85
86 IConfig xEngineConfig = configSource.AddConfig("XEngine");
87 xEngineConfig.Set("Enabled", "true");
88 xEngineConfig.Set("StartDelay", "0");
89
90 // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
91 // to AssemblyResolver.OnAssemblyResolve fails.
92 xEngineConfig.Set("AppDomainLoading", "false");
93
94 xEngineConfig.Set("ScriptStopStrategy", "co-op");
95
96 // Make sure loops aren't actually being terminated by a script delay wait.
97 xEngineConfig.Set("ScriptDelayFactor", 0);
98
99 // This is really just set for debugging the test.
100 xEngineConfig.Set("WriteScriptSourceToDebugFile", true);
101
102 // Set to false if we need to debug test so the old scripts don't get wiped before each separate test
103// xEngineConfig.Set("DeleteScriptsOnStartup", false);
104
105 // This is not currently used at all for co-op termination. Bumping up to demonstrate that co-op termination
106 // has an effect - without it tests will fail due to a 120 second wait for the event to finish.
107 xEngineConfig.Set("WaitForEventCompletionOnScriptStop", 120000);
108
109 m_scene = new SceneHelpers().SetupScene("My Test", TestHelpers.ParseTail(0x9999), 1000, 1000, configSource);
110 SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine);
111 m_scene.StartScripts();
112 }
113
114 /// <summary>
115 /// Test co-operative termination on derez of an object containing a script with a long-running event.
116 /// </summary>
117 /// <remarks>
118 /// TODO: Actually compiling the script is incidental to this test. Really want a way to compile test scripts
119 /// within the build itself.
120 /// </remarks>
121 [Test]
122 public void TestStopOnLongSleep()
123 {
124 TestHelpers.InMethod();
125// TestHelpers.EnableLogging();
126
127 string script =
128@"default
129{
130 state_entry()
131 {
132 llSay(0, ""Thin Lizzy"");
133 llSleep(60);
134 }
135}";
136
137 TestStop(script);
138 }
139
140 [Test]
141 public void TestNoStopOnSingleStatementForLoop()
142 {
143 TestHelpers.InMethod();
144// TestHelpers.EnableLogging();
145
146 string script =
147@"default
148{
149 state_entry()
150 {
151 integer i = 0;
152 for (i = 0; i <= 1; i++) llSay(0, ""Iter "" + (string)i);
153 }
154}";
155
156 TestSingleStatementNoStop(script);
157 }
158
159 [Test]
160 public void TestStopOnLongSingleStatementForLoop()
161 {
162 TestHelpers.InMethod();
163// TestHelpers.EnableLogging();
164
165 string script =
166@"default
167{
168 state_entry()
169 {
170 integer i = 0;
171 llSay(0, ""Thin Lizzy"");
172
173 for (i = 0; i < 2147483647; i++) llSay(0, ""Iter "" + (string)i);
174 }
175}";
176
177 TestStop(script);
178 }
179
180 [Test]
181 public void TestStopOnLongCompoundStatementForLoop()
182 {
183 TestHelpers.InMethod();
184// TestHelpers.EnableLogging();
185
186 string script =
187@"default
188{
189 state_entry()
190 {
191 integer i = 0;
192 llSay(0, ""Thin Lizzy"");
193
194 for (i = 0; i < 2147483647; i++)
195 {
196 llSay(0, ""Iter "" + (string)i);
197 }
198 }
199}";
200
201 TestStop(script);
202 }
203
204 [Test]
205 public void TestNoStopOnSingleStatementWhileLoop()
206 {
207 TestHelpers.InMethod();
208// TestHelpers.EnableLogging();
209
210 string script =
211@"default
212{
213 state_entry()
214 {
215 integer i = 0;
216 while (i < 2) llSay(0, ""Iter "" + (string)i++);
217 }
218}";
219
220 TestSingleStatementNoStop(script);
221 }
222
223 [Test]
224 public void TestStopOnLongSingleStatementWhileLoop()
225 {
226 TestHelpers.InMethod();
227// TestHelpers.EnableLogging();
228
229 string script =
230@"default
231{
232 state_entry()
233 {
234 integer i = 0;
235 llSay(0, ""Thin Lizzy"");
236
237 while (1 == 1)
238 llSay(0, ""Iter "" + (string)i++);
239 }
240}";
241
242 TestStop(script);
243 }
244
245 [Test]
246 public void TestStopOnLongCompoundStatementWhileLoop()
247 {
248 TestHelpers.InMethod();
249// TestHelpers.EnableLogging();
250
251 string script =
252@"default
253{
254 state_entry()
255 {
256 integer i = 0;
257 llSay(0, ""Thin Lizzy"");
258
259 while (1 == 1)
260 {
261 llSay(0, ""Iter "" + (string)i++);
262 }
263 }
264}";
265
266 TestStop(script);
267 }
268
269 [Test]
270 public void TestNoStopOnSingleStatementDoWhileLoop()
271 {
272 TestHelpers.InMethod();
273// TestHelpers.EnableLogging();
274
275 string script =
276@"default
277{
278 state_entry()
279 {
280 integer i = 0;
281
282 do llSay(0, ""Iter "" + (string)i++);
283 while (i < 2);
284 }
285}";
286
287 TestSingleStatementNoStop(script);
288 }
289
290 [Test]
291 public void TestStopOnLongSingleStatementDoWhileLoop()
292 {
293 TestHelpers.InMethod();
294// TestHelpers.EnableLogging();
295
296 string script =
297@"default
298{
299 state_entry()
300 {
301 integer i = 0;
302 llSay(0, ""Thin Lizzy"");
303
304 do llSay(0, ""Iter "" + (string)i++);
305 while (1 == 1);
306 }
307}";
308
309 TestStop(script);
310 }
311
312 [Test]
313 public void TestStopOnLongCompoundStatementDoWhileLoop()
314 {
315 TestHelpers.InMethod();
316// TestHelpers.EnableLogging();
317
318 string script =
319@"default
320{
321 state_entry()
322 {
323 integer i = 0;
324 llSay(0, ""Thin Lizzy"");
325
326 do
327 {
328 llSay(0, ""Iter "" + (string)i++);
329 } while (1 == 1);
330 }
331}";
332
333 TestStop(script);
334 }
335
336 [Test]
337 public void TestStopOnInfiniteJumpLoop()
338 {
339 TestHelpers.InMethod();
340// TestHelpers.EnableLogging();
341
342 string script =
343@"default
344{
345 state_entry()
346 {
347 integer i = 0;
348 llSay(0, ""Thin Lizzy"");
349
350 @p1;
351 llSay(0, ""Iter "" + (string)i++);
352 jump p1;
353 }
354}";
355
356 TestStop(script);
357 }
358
359 // Disabling for now as these are not particularly useful tests (since they fail due to stack overflow before
360 // termination can even be tried.
361// [Test]
362 public void TestStopOnInfiniteUserFunctionCallLoop()
363 {
364 TestHelpers.InMethod();
365// TestHelpers.EnableLogging();
366
367 string script =
368@"
369integer i = 0;
370
371ufn1()
372{
373 llSay(0, ""Iter ufn1() "" + (string)i++);
374 ufn1();
375}
376
377default
378{
379 state_entry()
380 {
381 integer i = 0;
382 llSay(0, ""Thin Lizzy"");
383
384 ufn1();
385 }
386}";
387
388 TestStop(script);
389 }
390
391 // Disabling for now as these are not particularly useful tests (since they fail due to stack overflow before
392 // termination can even be tried.
393// [Test]
394 public void TestStopOnInfiniteManualEventCallLoop()
395 {
396 TestHelpers.InMethod();
397// TestHelpers.EnableLogging();
398
399 string script =
400@"default
401{
402 state_entry()
403 {
404 integer i = 0;
405 llSay(0, ""Thin Lizzy"");
406
407 llSay(0, ""Iter"" + (string)i++);
408 default_event_state_entry();
409 }
410}";
411
412 TestStop(script);
413 }
414
415 private SceneObjectPart CreateScript(string script, string itemName, UUID userId)
416 {
417// UUID objectId = TestHelpers.ParseTail(0x100);
418// UUID itemId = TestHelpers.ParseTail(0x3);
419
420 SceneObjectGroup so
421 = SceneHelpers.CreateSceneObject(1, userId, string.Format("Object for {0}", itemName), 0x100);
422 m_scene.AddNewSceneObject(so, true);
423
424 InventoryItemBase itemTemplate = new InventoryItemBase();
425// itemTemplate.ID = itemId;
426 itemTemplate.Name = itemName;
427 itemTemplate.Folder = so.UUID;
428 itemTemplate.InvType = (int)InventoryType.LSL;
429
430 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
431
432 return m_scene.RezNewScript(userId, itemTemplate, script);
433 }
434
435 private void TestSingleStatementNoStop(string script)
436 {
437 // In these tests we expect to see at least 2 chat messages to confirm that the loop is working properly.
438 m_chatMessagesThreshold = 2;
439
440 UUID userId = TestHelpers.ParseTail(0x1);
441// UUID objectId = TestHelpers.ParseTail(0x100);
442// UUID itemId = TestHelpers.ParseTail(0x3);
443 string itemName = "TestNoStop";
444
445 SceneObjectPart partWhereRezzed = CreateScript(script, itemName, userId);
446 TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
447
448 // Wait for the script to start the event before we try stopping it.
449 m_chatEvent.WaitOne(60000);
450
451 if (m_osChatMessageReceived == null)
452 Assert.Fail("Script did not start");
453 else
454 Assert.That(m_chatMessagesReceived, Is.EqualTo(2));
455
456 bool running;
457 TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
458 Assert.That(
459 SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
460 Assert.That(running, Is.True);
461 }
462
463 private void TestStop(string script)
464 {
465 // In these tests we're only interested in the first message to confirm that the script has started.
466 m_chatMessagesThreshold = 1;
467
468 UUID userId = TestHelpers.ParseTail(0x1);
469// UUID objectId = TestHelpers.ParseTail(0x100);
470// UUID itemId = TestHelpers.ParseTail(0x3);
471 string itemName = "TestStop";
472
473 SceneObjectPart partWhereRezzed = CreateScript(script, itemName, userId);
474 TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
475
476 // Wait for the script to start the event before we try stopping it.
477 m_chatEvent.WaitOne(60000);
478
479 if (m_osChatMessageReceived != null)
480 Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message);
481 else
482 Assert.Fail("Script did not start");
483
484 // FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script
485 // executes llSay() but has not started the next statement before we try to stop it.
486 Thread.Sleep(1000);
487
488 // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually
489 // stopped. This kind of multi-threading is far from ideal in a regression test.
490 new Thread(() => { m_xEngine.StopScript(rezzedItem.ItemID); m_stoppedEvent.Set(); }).Start();
491
492 if (!m_stoppedEvent.WaitOne(30000))
493 Assert.Fail("Script did not co-operatively stop.");
494
495 bool running;
496 TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
497 Assert.That(
498 SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
499 Assert.That(running, Is.False);
500 }
501
502 private void OnChatFromWorld(object sender, OSChatMessage oscm)
503 {
504 Console.WriteLine("Got chat [{0}]", oscm.Message);
505 m_osChatMessageReceived = oscm;
506
507 if (++m_chatMessagesReceived >= m_chatMessagesThreshold)
508 {
509 m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
510 m_chatEvent.Set();
511 }
512 }
513 }
514} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index c9c4753..2e61fb8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -633,19 +633,44 @@ namespace OpenSim.Region.ScriptEngine.Shared
633 633
634 public LSL_Types.Vector3 GetVector3Item(int itemIndex) 634 public LSL_Types.Vector3 GetVector3Item(int itemIndex)
635 { 635 {
636 if(m_data[itemIndex] is LSL_Types.Vector3) 636 if (m_data[itemIndex] is LSL_Types.Vector3)
637 {
637 return (LSL_Types.Vector3)m_data[itemIndex]; 638 return (LSL_Types.Vector3)m_data[itemIndex];
639 }
640 else if(m_data[itemIndex] is OpenMetaverse.Vector3)
641 {
642 return new LSL_Types.Vector3(
643 (OpenMetaverse.Vector3)m_data[itemIndex]);
644 }
638 else 645 else
646 {
639 throw new InvalidCastException(string.Format( 647 throw new InvalidCastException(string.Format(
640 "{0} expected but {1} given", 648 "{0} expected but {1} given",
641 typeof(LSL_Types.Vector3).Name, 649 typeof(LSL_Types.Vector3).Name,
642 m_data[itemIndex] != null ? 650 m_data[itemIndex] != null ?
643 m_data[itemIndex].GetType().Name : "null")); 651 m_data[itemIndex].GetType().Name : "null"));
652 }
644 } 653 }
645 654
646 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) 655 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)
647 { 656 {
648 return (LSL_Types.Quaternion)m_data[itemIndex]; 657 if (m_data[itemIndex] is LSL_Types.Quaternion)
658 {
659 return (LSL_Types.Quaternion)m_data[itemIndex];
660 }
661 else if(m_data[itemIndex] is OpenMetaverse.Quaternion)
662 {
663 return new LSL_Types.Quaternion(
664 (OpenMetaverse.Quaternion)m_data[itemIndex]);
665 }
666 else
667 {
668 throw new InvalidCastException(string.Format(
669 "{0} expected but {1} given",
670 typeof(LSL_Types.Quaternion).Name,
671 m_data[itemIndex] != null ?
672 m_data[itemIndex].GetType().Name : "null"));
673 }
649 } 674 }
650 675
651 public LSL_Types.key GetKeyItem(int itemIndex) 676 public LSL_Types.key GetKeyItem(int itemIndex)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs
index e6e8777..d08b0a6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
index c73e22f..6dd6c17 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared; 42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api; 43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
44using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
45using OpenSim.Tests.Common; 46using OpenSim.Tests.Common;
46using OpenSim.Tests.Common.Mock; 47using OpenSim.Tests.Common.Mock;
@@ -51,14 +52,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 /// Tests for inventory functions in LSL 52 /// Tests for inventory functions in LSL
52 /// </summary> 53 /// </summary>
53 [TestFixture] 54 [TestFixture]
54 public class LSL_ApiInventoryTests 55 public class LSL_ApiInventoryTests : OpenSimTestCase
55 { 56 {
56 protected Scene m_scene; 57 protected Scene m_scene;
57 protected XEngine.XEngine m_engine; 58 protected XEngine.XEngine m_engine;
58 59
59 [SetUp] 60 [SetUp]
60 public void SetUp() 61 public override void SetUp()
61 { 62 {
63 base.SetUp();
64
62 IConfigSource initConfigSource = new IniConfigSource(); 65 IConfigSource initConfigSource = new IniConfigSource();
63 IConfig config = initConfigSource.AddConfig("XEngine"); 66 IConfig config = initConfigSource.AddConfig("XEngine");
64 config.Set("Enabled", "true"); 67 config.Set("Enabled", "true");
@@ -91,7 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
91 TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, userId); 94 TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, userId);
92 95
93 LSL_Api api = new LSL_Api(); 96 LSL_Api api = new LSL_Api();
94 api.Initialize(m_engine, so1.RootPart, null); 97 api.Initialize(m_engine, so1.RootPart, null, null);
95 98
96 // Create a second object 99 // Create a second object
97 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, userId, "so2", 0x100); 100 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, userId, "so2", 0x100);
@@ -124,7 +127,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
124 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10); 127 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10);
125 m_scene.AddSceneObject(so1); 128 m_scene.AddSceneObject(so1);
126 LSL_Api api = new LSL_Api(); 129 LSL_Api api = new LSL_Api();
127 api.Initialize(m_engine, so1.RootPart, null); 130 api.Initialize(m_engine, so1.RootPart, null, null);
128 131
129 // Create an object embedded inside the first 132 // Create an object embedded inside the first
130 UUID itemId = TestHelpers.ParseTail(0x20); 133 UUID itemId = TestHelpers.ParseTail(0x20);
@@ -134,7 +137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
134 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, user2Id, "so2", 0x100); 137 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, user2Id, "so2", 0x100);
135 m_scene.AddSceneObject(so2); 138 m_scene.AddSceneObject(so2);
136 LSL_Api api2 = new LSL_Api(); 139 LSL_Api api2 = new LSL_Api();
137 api2.Initialize(m_engine, so2.RootPart, null); 140 api2.Initialize(m_engine, so2.RootPart, null, null);
138 141
139 // *** Firstly, we test where llAllowInventoryDrop() has not been called. *** 142 // *** Firstly, we test where llAllowInventoryDrop() has not been called. ***
140 api.llGiveInventory(so2.UUID.ToString(), inventoryItemName); 143 api.llGiveInventory(so2.UUID.ToString(), inventoryItemName);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
index 2565ae7..5b57bbe 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared; 42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api; 43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
44using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 45using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
45using OpenSim.Services.Interfaces; 46using OpenSim.Services.Interfaces;
46using OpenSim.Tests.Common; 47using OpenSim.Tests.Common;
@@ -56,14 +57,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
56 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests. 57 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests.
57 /// </remarks> 58 /// </remarks>
58 [TestFixture] 59 [TestFixture]
59 public class LSL_ApiLinkingTests 60 public class LSL_ApiLinkingTests : OpenSimTestCase
60 { 61 {
61 protected Scene m_scene; 62 protected Scene m_scene;
62 protected XEngine.XEngine m_engine; 63 protected XEngine.XEngine m_engine;
63 64
64 [SetUp] 65 [SetUp]
65 public void SetUp() 66 public override void SetUp()
66 { 67 {
68 base.SetUp();
69
67 IConfigSource initConfigSource = new IniConfigSource(); 70 IConfigSource initConfigSource = new IniConfigSource();
68 IConfig config = initConfigSource.AddConfig("XEngine"); 71 IConfig config = initConfigSource.AddConfig("XEngine");
69 config.Set("Enabled", "true"); 72 config.Set("Enabled", "true");
@@ -102,7 +105,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
102 m_scene.AddSceneObject(grp2); 105 m_scene.AddSceneObject(grp2);
103 106
104 LSL_Api apiGrp1 = new LSL_Api(); 107 LSL_Api apiGrp1 = new LSL_Api();
105 apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item); 108 apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item, null);
106 109
107 apiGrp1.llCreateLink(grp2.UUID.ToString(), ScriptBaseClass.TRUE); 110 apiGrp1.llCreateLink(grp2.UUID.ToString(), ScriptBaseClass.TRUE);
108 111
@@ -129,7 +132,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
129 grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 132 grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
130 133
131 LSL_Api apiGrp1 = new LSL_Api(); 134 LSL_Api apiGrp1 = new LSL_Api();
132 apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item); 135 apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item, null);
133 136
134 apiGrp1.llBreakLink(2); 137 apiGrp1.llBreakLink(2);
135 138
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
index dd23be8..60de5cb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
@@ -34,6 +34,7 @@ using OpenSim.Region.ScriptEngine.Shared;
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35using Nini.Config; 35using Nini.Config;
36using OpenSim.Region.ScriptEngine.Shared.Api; 36using OpenSim.Region.ScriptEngine.Shared.Api;
37using OpenSim.Region.ScriptEngine.Shared.Instance;
37using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 38using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
38using OpenMetaverse; 39using OpenMetaverse;
39using OpenSim.Tests.Common.Mock; 40using OpenSim.Tests.Common.Mock;
@@ -46,13 +47,15 @@ using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
46namespace OpenSim.Region.ScriptEngine.Shared.Tests 47namespace OpenSim.Region.ScriptEngine.Shared.Tests
47{ 48{
48 [TestFixture] 49 [TestFixture]
49 public class LSL_ApiListTests 50 public class LSL_ApiListTests : OpenSimTestCase
50 { 51 {
51 private LSL_Api m_lslApi; 52 private LSL_Api m_lslApi;
52 53
53 [SetUp] 54 [SetUp]
54 public void SetUp() 55 public override void SetUp()
55 { 56 {
57 base.SetUp();
58
56 IConfigSource initConfigSource = new IniConfigSource(); 59 IConfigSource initConfigSource = new IniConfigSource();
57 IConfig config = initConfigSource.AddConfig("XEngine"); 60 IConfig config = initConfigSource.AddConfig("XEngine");
58 config.Set("Enabled", "true"); 61 config.Set("Enabled", "true");
@@ -65,7 +68,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
65 engine.AddRegion(scene); 68 engine.AddRegion(scene);
66 69
67 m_lslApi = new LSL_Api(); 70 m_lslApi = new LSL_Api();
68 m_lslApi.Initialize(engine, part, null); 71 m_lslApi.Initialize(engine, part, null, null);
69 } 72 }
70 73
71 [Test] 74 [Test]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
index c41d1e7..e97ae06 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
@@ -33,6 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
34using Nini.Config; 34using Nini.Config;
35using OpenSim.Region.ScriptEngine.Shared.Api; 35using OpenSim.Region.ScriptEngine.Shared.Api;
36using OpenSim.Region.ScriptEngine.Shared.Instance;
36using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 37using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
37using OpenMetaverse; 38using OpenMetaverse;
38using System; 39using System;
@@ -66,7 +67,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
66 engine.AddRegion(scene); 67 engine.AddRegion(scene);
67 68
68 m_lslApi = new LSL_Api(); 69 m_lslApi = new LSL_Api();
69 m_lslApi.Initialize(engine, part, null); 70 m_lslApi.Initialize(engine, part, null, null);
70 } 71 }
71 72
72 [Test] 73 [Test]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
index 3ed2562..c8c7f82 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLFloat 36 public class LSL_TypesTestLSLFloat : OpenSimTestCase
37 { 37 {
38 // Used for testing equality of two floats. 38 // Used for testing equality of two floats.
39 private double _lowPrecisionTolerance = 0.000001; 39 private double _lowPrecisionTolerance = 0.000001;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
index 8d1169a..c664108 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLInteger 36 public class LSL_TypesTestLSLInteger : OpenSimTestCase
37 { 37 {
38 private Dictionary<double, int> m_doubleIntSet; 38 private Dictionary<double, int> m_doubleIntSet;
39 private Dictionary<string, int> m_stringIntSet; 39 private Dictionary<string, int> m_stringIntSet;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
index c4ca1a8..8550f2d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLString 36 public class LSL_TypesTestLSLString : OpenSimTestCase
37 { 37 {
38 private Dictionary<double, string> m_doubleStringSet; 38 private Dictionary<double, string> m_doubleStringSet;
39 39
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
index b81225f..71b88bc 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
36 /// Tests the LSL_Types.list class. 36 /// Tests the LSL_Types.list class.
37 /// </summary> 37 /// </summary>
38 [TestFixture] 38 [TestFixture]
39 public class LSL_TypesTestList 39 public class LSL_TypesTestList : OpenSimTestCase
40 { 40 {
41 /// <summary> 41 /// <summary>
42 /// Tests concatenating a string to a list. 42 /// Tests concatenating a string to a list.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
index ebf8001..0c838af 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
36 /// Tests for Vector3 36 /// Tests for Vector3
37 /// </summary> 37 /// </summary>
38 [TestFixture] 38 [TestFixture]
39 public class LSL_TypesTestVector3 39 public class LSL_TypesTestVector3 : OpenSimTestCase
40 { 40 {
41 [Test] 41 [Test]
42 public void TestDotProduct() 42 public void TestDotProduct()
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
index c401794..c88bad5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared; 42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api; 43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
44using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
45using OpenSim.Tests.Common; 46using OpenSim.Tests.Common;
46using OpenSim.Tests.Common.Mock; 47using OpenSim.Tests.Common.Mock;
@@ -51,14 +52,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 /// Tests for OSSL_Api 52 /// Tests for OSSL_Api
52 /// </summary> 53 /// </summary>
53 [TestFixture] 54 [TestFixture]
54 public class OSSL_ApiAppearanceTest 55 public class OSSL_ApiAppearanceTest : OpenSimTestCase
55 { 56 {
56 protected Scene m_scene; 57 protected Scene m_scene;
57 protected XEngine.XEngine m_engine; 58 protected XEngine.XEngine m_engine;
58 59
59 [SetUp] 60 [SetUp]
60 public void SetUp() 61 public override void SetUp()
61 { 62 {
63 base.SetUp();
64
62 IConfigSource initConfigSource = new IniConfigSource(); 65 IConfigSource initConfigSource = new IniConfigSource();
63 IConfig config = initConfigSource.AddConfig("XEngine"); 66 IConfig config = initConfigSource.AddConfig("XEngine");
64 config.Set("Enabled", "true"); 67 config.Set("Enabled", "true");
@@ -91,7 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
91 m_scene.AddSceneObject(so); 94 m_scene.AddSceneObject(so);
92 95
93 OSSL_Api osslApi = new OSSL_Api(); 96 OSSL_Api osslApi = new OSSL_Api();
94 osslApi.Initialize(m_engine, part, null); 97 osslApi.Initialize(m_engine, part, null, null);
95 98
96 string notecardName = "appearanceNc"; 99 string notecardName = "appearanceNc";
97 100
@@ -132,7 +135,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
132 m_scene.AddSceneObject(so); 135 m_scene.AddSceneObject(so);
133 136
134 OSSL_Api osslApi = new OSSL_Api(); 137 OSSL_Api osslApi = new OSSL_Api();
135 osslApi.Initialize(m_engine, part, null); 138 osslApi.Initialize(m_engine, part, null, null);
136 139
137 string notecardName = "appearanceNc"; 140 string notecardName = "appearanceNc";
138 141
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
index 5ed1f3d..b2803a1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.CoreModules.Framework.InventoryAccess;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared; 42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api; 43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
44using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
45using OpenSim.Tests.Common; 46using OpenSim.Tests.Common;
46using OpenSim.Tests.Common.Mock; 47using OpenSim.Tests.Common.Mock;
@@ -98,9 +99,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
98 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); 99 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
99 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart); 100 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
100 101
101 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem); 102 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
102 OSSL_Api osslApi = new OSSL_Api(); 103 OSSL_Api osslApi = new OSSL_Api();
103 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem); 104 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
104 105
105// SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ua1.PrincipalID); 106// SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ua1.PrincipalID);
106 107
@@ -144,9 +145,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
144 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); 145 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
145 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart); 146 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
146 147
147 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem); 148 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
148 OSSL_Api osslApi = new OSSL_Api(); 149 OSSL_Api osslApi = new OSSL_Api();
149 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem); 150 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
150 151
151 // Create an object embedded inside the first 152 // Create an object embedded inside the first
152 TaskInventoryHelpers.AddNotecard( 153 TaskInventoryHelpers.AddNotecard(
@@ -192,12 +193,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
192 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); 193 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
193 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart); 194 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
194 195
195 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem); 196 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
196 OSSL_Api osslApi = new OSSL_Api(); 197 OSSL_Api osslApi = new OSSL_Api();
197 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem); 198 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
198 199
199 // Create an object embedded inside the first 200 // Create an object embedded inside the first
200 TaskInventoryHelpers.AddSceneObject(m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID); 201 TaskInventoryHelpers.AddSceneObject(
202 m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID);
201 203
202 ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, ua2); 204 ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, ua2);
203 205
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
index b49bcc2..1f8a6e5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
@@ -42,6 +42,7 @@ using OpenSim.Region.OptionalModules.World.NPC;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.ScriptEngine.Shared; 43using OpenSim.Region.ScriptEngine.Shared;
44using OpenSim.Region.ScriptEngine.Shared.Api; 44using OpenSim.Region.ScriptEngine.Shared.Api;
45using OpenSim.Region.ScriptEngine.Shared.Instance;
45using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 46using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
46using OpenSim.Services.Interfaces; 47using OpenSim.Services.Interfaces;
47using OpenSim.Tests.Common; 48using OpenSim.Tests.Common;
@@ -99,7 +100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
99 m_scene.AddSceneObject(so); 100 m_scene.AddSceneObject(so);
100 101
101 OSSL_Api osslApi = new OSSL_Api(); 102 OSSL_Api osslApi = new OSSL_Api();
102 osslApi.Initialize(m_engine, part, null); 103 osslApi.Initialize(m_engine, part, null, null);
103 104
104 string notecardName = "appearanceNc"; 105 string notecardName = "appearanceNc";
105 osslApi.osOwnerSaveAppearance(notecardName); 106 osslApi.osOwnerSaveAppearance(notecardName);
@@ -125,14 +126,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
125 m_scene.AddSceneObject(so); 126 m_scene.AddSceneObject(so);
126 127
127 OSSL_Api osslApi = new OSSL_Api(); 128 OSSL_Api osslApi = new OSSL_Api();
128 osslApi.Initialize(m_engine, so.RootPart, null); 129 osslApi.Initialize(m_engine, so.RootPart, null, null);
129 130
130 string npcRaw;
131 bool gotExpectedException = false; 131 bool gotExpectedException = false;
132 try 132 try
133 { 133 {
134 npcRaw 134 osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
135 = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
136 } 135 }
137 catch (ScriptException) 136 catch (ScriptException)
138 { 137 {
@@ -162,7 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
162 m_scene.AddSceneObject(so); 161 m_scene.AddSceneObject(so);
163 162
164 OSSL_Api osslApi = new OSSL_Api(); 163 OSSL_Api osslApi = new OSSL_Api();
165 osslApi.Initialize(m_engine, part, null); 164 osslApi.Initialize(m_engine, part, null, null);
166 165
167 string notecardName = "appearanceNc"; 166 string notecardName = "appearanceNc";
168 osslApi.osOwnerSaveAppearance(notecardName); 167 osslApi.osOwnerSaveAppearance(notecardName);
@@ -196,7 +195,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
196 m_scene.AddSceneObject(so); 195 m_scene.AddSceneObject(so);
197 196
198 OSSL_Api osslApi = new OSSL_Api(); 197 OSSL_Api osslApi = new OSSL_Api();
199 osslApi.Initialize(m_engine, part, null); 198 osslApi.Initialize(m_engine, part, null, null);
200 199
201 osslApi.osOwnerSaveAppearance(firstAppearanceNcName); 200 osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
202 201
@@ -234,7 +233,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
234 m_scene.AddSceneObject(so); 233 m_scene.AddSceneObject(so);
235 234
236 OSSL_Api osslApi = new OSSL_Api(); 235 OSSL_Api osslApi = new OSSL_Api();
237 osslApi.Initialize(m_engine, part, null); 236 osslApi.Initialize(m_engine, part, null, null);
238 237
239 osslApi.osOwnerSaveAppearance(firstAppearanceNcName); 238 osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
240 239
@@ -286,10 +285,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
286 m_scene.AddSceneObject(otherSo); 285 m_scene.AddSceneObject(otherSo);
287 286
288 OSSL_Api osslApi = new OSSL_Api(); 287 OSSL_Api osslApi = new OSSL_Api();
289 osslApi.Initialize(m_engine, part, null); 288 osslApi.Initialize(m_engine, part, null, null);
290 289
291 OSSL_Api otherOsslApi = new OSSL_Api(); 290 OSSL_Api otherOsslApi = new OSSL_Api();
292 otherOsslApi.Initialize(m_engine, otherPart, null); 291 otherOsslApi.Initialize(m_engine, otherPart, null, null);
293 292
294 string notecardName = "appearanceNc"; 293 string notecardName = "appearanceNc";
295 osslApi.osOwnerSaveAppearance(notecardName); 294 osslApi.osOwnerSaveAppearance(notecardName);
@@ -333,7 +332,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
333 m_scene.AddSceneObject(so); 332 m_scene.AddSceneObject(so);
334 333
335 OSSL_Api osslApi = new OSSL_Api(); 334 OSSL_Api osslApi = new OSSL_Api();
336 osslApi.Initialize(m_engine, part, null); 335 osslApi.Initialize(m_engine, part, null, null);
337 336
338 string notecardName = "appearanceNc"; 337 string notecardName = "appearanceNc";
339 osslApi.osOwnerSaveAppearance(notecardName); 338 osslApi.osOwnerSaveAppearance(notecardName);
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs b/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs
new file mode 100644
index 0000000..f4211c8
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.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.Runtime.Remoting;
30using System.Runtime.Remoting.Lifetime;
31using System.Security.Permissions;
32using System.Threading;
33using System.Reflection;
34using System.Collections;
35using System.Collections.Generic;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
39
40namespace OpenSim.Region.ScriptEngine.XEngine.ScriptBase
41{
42 public class XEngineScriptBase : ScriptBaseClass
43 {
44 /// <summary>
45 /// Used for script sleeps when we are using co-operative script termination.
46 /// </summary>
47 /// <remarks>null if co-operative script termination is not active</remarks>
48 WaitHandle m_coopSleepHandle;
49
50 public XEngineScriptBase(WaitHandle coopSleepHandle) : base()
51 {
52 m_coopSleepHandle = coopSleepHandle;
53 }
54
55 public void opensim_reserved_CheckForCoopTermination()
56 {
57 if (m_coopSleepHandle != null && m_coopSleepHandle.WaitOne(0))
58 throw new ScriptCoopStopException();
59 }
60 }
61} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index 9405075..0ff2da3 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
52 { 52 {
53 myScriptEngine = _ScriptEngine; 53 myScriptEngine = _ScriptEngine;
54 54
55 m_log.Info("[XEngine] Hooking up to server events"); 55// m_log.Info("[XEngine] Hooking up to server events");
56 myScriptEngine.World.EventManager.OnAttach += attach; 56 myScriptEngine.World.EventManager.OnAttach += attach;
57 myScriptEngine.World.EventManager.OnObjectGrab += touch_start; 57 myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
58 myScriptEngine.World.EventManager.OnObjectGrabbing += touch; 58 myScriptEngine.World.EventManager.OnObjectGrabbing += touch;
@@ -62,6 +62,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
62 myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target; 62 myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target;
63 myScriptEngine.World.EventManager.OnScriptAtRotTargetEvent += at_rot_target; 63 myScriptEngine.World.EventManager.OnScriptAtRotTargetEvent += at_rot_target;
64 myScriptEngine.World.EventManager.OnScriptNotAtRotTargetEvent += not_at_rot_target; 64 myScriptEngine.World.EventManager.OnScriptNotAtRotTargetEvent += not_at_rot_target;
65 myScriptEngine.World.EventManager.OnScriptMovingStartEvent += moving_start;
66 myScriptEngine.World.EventManager.OnScriptMovingEndEvent += moving_end;
65 myScriptEngine.World.EventManager.OnScriptControlEvent += control; 67 myScriptEngine.World.EventManager.OnScriptControlEvent += control;
66 myScriptEngine.World.EventManager.OnScriptColliderStart += collision_start; 68 myScriptEngine.World.EventManager.OnScriptColliderStart += collision_start;
67 myScriptEngine.World.EventManager.OnScriptColliding += collision; 69 myScriptEngine.World.EventManager.OnScriptColliding += collision;
@@ -69,7 +71,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
69 myScriptEngine.World.EventManager.OnScriptLandColliderStart += land_collision_start; 71 myScriptEngine.World.EventManager.OnScriptLandColliderStart += land_collision_start;
70 myScriptEngine.World.EventManager.OnScriptLandColliding += land_collision; 72 myScriptEngine.World.EventManager.OnScriptLandColliding += land_collision;
71 myScriptEngine.World.EventManager.OnScriptLandColliderEnd += land_collision_end; 73 myScriptEngine.World.EventManager.OnScriptLandColliderEnd += land_collision_end;
72 IMoneyModule money=myScriptEngine.World.RequestModuleInterface<IMoneyModule>(); 74 IMoneyModule money = myScriptEngine.World.RequestModuleInterface<IMoneyModule>();
73 if (money != null) 75 if (money != null)
74 { 76 {
75 money.OnObjectPaid+=HandleObjectPaid; 77 money.OnObjectPaid+=HandleObjectPaid;
@@ -419,14 +421,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
419 // dataserver: not handled here 421 // dataserver: not handled here
420 // link_message: not handled here 422 // link_message: not handled here
421 423
422 public void moving_start(uint localID, UUID itemID) 424 public void moving_start(uint localID)
423 { 425 {
424 myScriptEngine.PostObjectEvent(localID, new EventParams( 426 myScriptEngine.PostObjectEvent(localID, new EventParams(
425 "moving_start",new object[0], 427 "moving_start",new object[0],
426 new DetectParams[0])); 428 new DetectParams[0]));
427 } 429 }
428 430
429 public void moving_end(uint localID, UUID itemID) 431 public void moving_end(uint localID)
430 { 432 {
431 myScriptEngine.PostObjectEvent(localID, new EventParams( 433 myScriptEngine.PostObjectEvent(localID, new EventParams(
432 "moving_end",new object[0], 434 "moving_end",new object[0],
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
index bd26a8b..a887171 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs
new file mode 100644
index 0000000..efb854d
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs
@@ -0,0 +1,126 @@
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 OpenSim.Framework;
31using OpenSim.Framework.Console;
32using OpenSim.Region.ScriptEngine.Interfaces;
33using OpenSim.Region.ScriptEngine.Shared.Api;
34using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
35
36namespace OpenSim.Region.ScriptEngine.XEngine
37{
38 public class ScriptEngineConsoleCommands
39 {
40 IScriptEngine m_engine;
41
42 public ScriptEngineConsoleCommands(IScriptEngine engine)
43 {
44 m_engine = engine;
45 }
46
47 public void RegisterCommands()
48 {
49 MainConsole.Instance.Commands.AddCommand(
50 "Scripts", false, "show script sensors", "show script sensors", "Show script sensors information",
51 HandleShowSensors);
52
53 MainConsole.Instance.Commands.AddCommand(
54 "Scripts", false, "show script timers", "show script timers", "Show script sensors information",
55 HandleShowTimers);
56 }
57
58 private bool IsSceneSelected()
59 {
60 return MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_engine.World;
61 }
62
63 private void HandleShowSensors(string module, string[] cmdparams)
64 {
65 if (!IsSceneSelected())
66 return;
67
68 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(m_engine);
69
70 if (sr == null)
71 {
72 MainConsole.Instance.Output("Plugin not yet initialized");
73 return;
74 }
75
76 List<SensorRepeat.SensorInfo> sensorInfo = sr.GetSensorInfo();
77
78 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
79 cdt.AddColumn("Part name", 40);
80 cdt.AddColumn("Script item ID", 36);
81 cdt.AddColumn("Type", 4);
82 cdt.AddColumn("Interval", 8);
83 cdt.AddColumn("Range", 8);
84 cdt.AddColumn("Arc", 8);
85
86 foreach (SensorRepeat.SensorInfo s in sensorInfo)
87 {
88 cdt.AddRow(s.host.Name, s.itemID, s.type, s.interval, s.range, s.arc);
89 }
90
91 MainConsole.Instance.Output(cdt.ToString());
92 MainConsole.Instance.OutputFormat("Total: {0}", sensorInfo.Count);
93 }
94
95 private void HandleShowTimers(string module, string[] cmdparams)
96 {
97 if (!IsSceneSelected())
98 return;
99
100 Timer timerPlugin = AsyncCommandManager.GetTimerPlugin(m_engine);
101
102 if (timerPlugin == null)
103 {
104 MainConsole.Instance.Output("Plugin not yet initialized");
105 return;
106 }
107
108 List<Timer.TimerInfo> timersInfo = timerPlugin.GetTimersInfo();
109
110 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
111 cdt.AddColumn("Part local ID", 13);
112 cdt.AddColumn("Script item ID", 36);
113 cdt.AddColumn("Interval", 10);
114 cdt.AddColumn("Next", 8);
115
116 foreach (Timer.TimerInfo t in timersInfo)
117 {
118 // Convert from 100 ns ticks back to seconds
119 cdt.AddRow(t.localID, t.itemID, (double)t.interval / 10000000, t.next);
120 }
121
122 MainConsole.Instance.Output(cdt.ToString());
123 MainConsole.Instance.OutputFormat("Total: {0}", timersInfo.Count);
124 }
125 }
126} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
index f331658..5abfe9a 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
44 /// XEngine tests. 44 /// XEngine tests.
45 /// </summary> 45 /// </summary>
46 [TestFixture] 46 [TestFixture]
47 public class XEngineTest 47 public class XEngineTest : OpenSimTestCase
48 { 48 {
49 private TestScene m_scene; 49 private TestScene m_scene;
50 private XEngine m_xEngine; 50 private XEngine m_xEngine;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 9f05666..17243ab 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode] 31using System.Diagnostics; //for [DebuggerNonUserCode]
32using System.Globalization; 32using System.Globalization;
33using System.IO; 33using System.IO;
34using System.Linq;
34using System.Reflection; 35using System.Reflection;
35using System.Security; 36using System.Security;
36using System.Security.Policy; 37using System.Security.Policy;
@@ -46,13 +47,14 @@ using OpenSim.Framework;
46using OpenSim.Framework.Console; 47using OpenSim.Framework.Console;
47using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Framework.Interfaces; 49using OpenSim.Region.Framework.Interfaces;
50using OpenSim.Region.ScriptEngine.Interfaces;
49using OpenSim.Region.ScriptEngine.Shared; 51using OpenSim.Region.ScriptEngine.Shared;
50using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
51using OpenSim.Region.ScriptEngine.Shared.CodeTools; 52using OpenSim.Region.ScriptEngine.Shared.CodeTools;
52using OpenSim.Region.ScriptEngine.Shared.Instance; 53using OpenSim.Region.ScriptEngine.Shared.Instance;
53using OpenSim.Region.ScriptEngine.Shared.Api; 54using OpenSim.Region.ScriptEngine.Shared.Api;
54using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 55using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
55using OpenSim.Region.ScriptEngine.Interfaces; 56using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
57using OpenSim.Region.ScriptEngine.XEngine.ScriptBase;
56using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; 58using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
57 59
58using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>; 60using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>;
@@ -107,6 +109,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
107 private IXmlRpcRouter m_XmlRpcRouter; 109 private IXmlRpcRouter m_XmlRpcRouter;
108 private int m_EventLimit; 110 private int m_EventLimit;
109 private bool m_KillTimedOutScripts; 111 private bool m_KillTimedOutScripts;
112
113 /// <summary>
114 /// Number of milliseconds we will wait for a script event to complete on script stop before we forcibly abort
115 /// its thread.
116 /// </summary>
117 /// <remarks>
118 /// It appears that if a script thread is aborted whilst it is holding ReaderWriterLockSlim (possibly the write
119 /// lock) then the lock is not properly released. This causes mono 2.6, 2.10 and possibly
120 /// later to crash, sometimes with symptoms such as a leap to 100% script usage and a vm thead dump showing
121 /// all threads waiting on release of ReaderWriterLockSlim write thread which none of the threads listed
122 /// actually hold.
123 ///
124 /// Pausing for event completion reduces the risk of this happening. However, it may be that aborting threads
125 /// is not a mono issue per se but rather a risky activity in itself in an AppDomain that is not immediately
126 /// shutting down.
127 /// </remarks>
128 private int m_WaitForEventCompletionOnScriptStop = 1000;
129
110 private string m_ScriptEnginesPath = null; 130 private string m_ScriptEnginesPath = null;
111 131
112 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>(); 132 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
@@ -218,11 +238,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
218 } 238 }
219 } 239 }
220 240
241 private ScriptEngineConsoleCommands m_consoleCommands;
242
221 public string ScriptEngineName 243 public string ScriptEngineName
222 { 244 {
223 get { return "XEngine"; } 245 get { return "XEngine"; }
224 } 246 }
225 247
248 public string ScriptClassName { get; private set; }
249
250 public string ScriptBaseClassName { get; private set; }
251
252 public ParameterInfo[] ScriptBaseClassParameters { get; private set; }
253
254 public string[] ScriptReferencedAssemblies { get; private set; }
255
226 public Scene World 256 public Scene World
227 { 257 {
228 get { return m_Scene; } 258 get { return m_Scene; }
@@ -277,21 +307,35 @@ namespace OpenSim.Region.ScriptEngine.XEngine
277 307
278 m_ScriptConfig = configSource.Configs["XEngine"]; 308 m_ScriptConfig = configSource.Configs["XEngine"];
279 m_ConfigSource = configSource; 309 m_ConfigSource = configSource;
310
311 string rawScriptStopStrategy = m_ScriptConfig.GetString("ScriptStopStrategy", "abort");
312
313 m_log.InfoFormat("[XEngine]: Script stop strategy is {0}", rawScriptStopStrategy);
314
315 if (rawScriptStopStrategy == "co-op")
316 {
317 ScriptClassName = "XEngineScript";
318 ScriptBaseClassName = typeof(XEngineScriptBase).FullName;
319 ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters();
320 ScriptReferencedAssemblies = new string[] { Path.GetFileName(typeof(XEngineScriptBase).Assembly.Location) };
321 }
322 else
323 {
324 ScriptClassName = "Script";
325 ScriptBaseClassName = typeof(ScriptBaseClass).FullName;
326 }
327
328// Console.WriteLine("ASSEMBLY NAME: {0}", ScriptReferencedAssemblies[0]);
280 } 329 }
281 330
282 public void AddRegion(Scene scene) 331 public void AddRegion(Scene scene)
283 { 332 {
284 if (m_ScriptConfig == null) 333 if (m_ScriptConfig == null)
285 return; 334 return;
335
286 m_ScriptFailCount = 0; 336 m_ScriptFailCount = 0;
287 m_ScriptErrorMessage = String.Empty; 337 m_ScriptErrorMessage = String.Empty;
288 338
289 if (m_ScriptConfig == null)
290 {
291// m_log.ErrorFormat("[XEngine] No script configuration found. Scripts disabled");
292 return;
293 }
294
295 m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true); 339 m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true);
296 340
297 if (!m_Enabled) 341 if (!m_Enabled)
@@ -316,6 +360,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
316 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); 360 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
317 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); 361 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
318 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; 362 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000;
363 m_WaitForEventCompletionOnScriptStop
364 = m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop);
365
319 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); 366 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines");
320 367
321 m_Prio = ThreadPriority.BelowNormal; 368 m_Prio = ThreadPriority.BelowNormal;
@@ -364,48 +411,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine
364 OnObjectRemoved += m_XmlRpcRouter.ObjectRemoved; 411 OnObjectRemoved += m_XmlRpcRouter.ObjectRemoved;
365 } 412 }
366 413
414 m_consoleCommands = new ScriptEngineConsoleCommands(this);
415 m_consoleCommands.RegisterCommands();
416
367 MainConsole.Instance.Commands.AddCommand( 417 MainConsole.Instance.Commands.AddCommand(
368 "Scripts", false, "xengine status", "xengine status", "Show status information", 418 "Scripts", false, "xengine status", "xengine status", "Show status information",
369 "Show status information on the script engine.", 419 "Show status information on the script engine.",
370 HandleShowStatus); 420 HandleShowStatus);
371 421
372 MainConsole.Instance.Commands.AddCommand( 422 MainConsole.Instance.Commands.AddCommand(
373 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", 423 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>+]", "Show script information",
374 "Show information on all scripts known to the script engine." 424 "Show information on all scripts known to the script engine.\n"
375 + "If a <script-item-uuid> is given then only information on that script will be shown.", 425 + "If one or more <script-item-uuid>s are given then only information on that script will be shown.",
376 HandleShowScripts); 426 HandleShowScripts);
377 427
378 MainConsole.Instance.Commands.AddCommand( 428 MainConsole.Instance.Commands.AddCommand(
379 "Scripts", false, "show scripts", "show scripts [<script-item-uuid>]", "Show script information", 429 "Scripts", false, "show scripts", "show scripts [<script-item-uuid>+]", "Show script information",
380 "Synonym for scripts show command", HandleShowScripts); 430 "Synonym for scripts show command", HandleShowScripts);
381 431
382 MainConsole.Instance.Commands.AddCommand( 432 MainConsole.Instance.Commands.AddCommand(
383 "Scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>]", "Suspends all running scripts", 433 "Scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>+]", "Suspends all running scripts",
384 "Suspends all currently running scripts. This only suspends event delivery, it will not suspend a" 434 "Suspends all currently running scripts. This only suspends event delivery, it will not suspend a"
385 + " script that is currently processing an event.\n" 435 + " script that is currently processing an event.\n"
386 + "Suspended scripts will continue to accumulate events but won't process them.\n" 436 + "Suspended scripts will continue to accumulate events but won't process them.\n"
387 + "If a <script-item-uuid> is given then only that script will be suspended. Otherwise, all suitable scripts are suspended.", 437 + "If one or more <script-item-uuid>s are given then only that script will be suspended. Otherwise, all suitable scripts are suspended.",
388 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleSuspendScript)); 438 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleSuspendScript));
389 439
390 MainConsole.Instance.Commands.AddCommand( 440 MainConsole.Instance.Commands.AddCommand(
391 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", 441 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>+]", "Resumes all suspended scripts",
392 "Resumes all currently suspended scripts.\n" 442 "Resumes all currently suspended scripts.\n"
393 + "Resumed scripts will process all events accumulated whilst suspended." 443 + "Resumed scripts will process all events accumulated whilst suspended.\n"
394 + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.", 444 + "If one or more <script-item-uuid>s are given then only that script will be resumed. Otherwise, all suitable scripts are resumed.",
395 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript)); 445 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
396 446
397 MainConsole.Instance.Commands.AddCommand( 447 MainConsole.Instance.Commands.AddCommand(
398 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", 448 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>+]", "Stops all running scripts",
399 "Stops all running scripts." 449 "Stops all running scripts.\n"
400 + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.", 450 + "If one or more <script-item-uuid>s are given then only that script will be stopped. Otherwise, all suitable scripts are stopped.",
401 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript)); 451 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
402 452
403 MainConsole.Instance.Commands.AddCommand( 453 MainConsole.Instance.Commands.AddCommand(
404 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", 454 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>+]", "Starts all stopped scripts",
405 "Starts all stopped scripts." 455 "Starts all stopped scripts.\n"
406 + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", 456 + "If one or more <script-item-uuid>s are given then only that script will be started. Otherwise, all suitable scripts are started.",
407 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); 457 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
408 458
459 MainConsole.Instance.Commands.AddCommand(
460 "Scripts", false, "debug scripts log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script",
461 "Activates or deactivates extra debug logging for the given script.\n"
462 + "Level == 0, deactivate extra debug logging.\n"
463 + "Level >= 1, log state changes.\n"
464 + "Level >= 2, log event invocations.\n",
465 HandleDebugScriptLogCommand);
466
409// MainConsole.Instance.Commands.AddCommand( 467// MainConsole.Instance.Commands.AddCommand(
410// "Debug", false, "debug xengine", "debug xengine [<level>]", 468// "Debug", false, "debug xengine", "debug xengine [<level>]",
411// "Turn on detailed xengine debugging.", 469// "Turn on detailed xengine debugging.",
@@ -414,6 +472,41 @@ namespace OpenSim.Region.ScriptEngine.XEngine
414// HandleDebugLevelCommand); 472// HandleDebugLevelCommand);
415 } 473 }
416 474
475 private void HandleDebugScriptLogCommand(string module, string[] args)
476 {
477 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
478 return;
479
480 if (args.Length != 5)
481 {
482 MainConsole.Instance.Output("Usage: debug script log <item-id> <log-level>");
483 return;
484 }
485
486 UUID itemId;
487
488 if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, args[3], out itemId))
489 return;
490
491 int newLevel;
492
493 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out newLevel))
494 return;
495
496 IScriptInstance si;
497
498 lock (m_Scripts)
499 {
500 // XXX: We can't give the user feedback on a bad item id because this may apply to a different script
501 // engine
502 if (!m_Scripts.TryGetValue(itemId, out si))
503 return;
504 }
505
506 si.DebugLevel = newLevel;
507 MainConsole.Instance.OutputFormat("Set debug level of {0} {1} to {2}", si.ScriptName, si.ItemID, newLevel);
508 }
509
417 /// <summary> 510 /// <summary>
418 /// Change debug level 511 /// Change debug level
419 /// </summary> 512 /// </summary>
@@ -445,9 +538,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
445 /// </summary> 538 /// </summary>
446 /// <param name="cmdparams"></param> 539 /// <param name="cmdparams"></param>
447 /// <param name="instance"></param> 540 /// <param name="instance"></param>
448 /// <returns>true if we're okay to proceed, false if not.</returns> 541 /// <param name="comparer">Basis on which to sort output. Can be null if no sort needs to take place</param>
449 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action) 542 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action)
450 { 543 {
544 HandleScriptsAction<object>(cmdparams, action, null);
545 }
546
547 /// <summary>
548 /// Parse the raw item id into a script instance from the command params if it's present.
549 /// </summary>
550 /// <param name="cmdparams"></param>
551 /// <param name="instance"></param>
552 /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
553 private void HandleScriptsAction<TKey>(
554 string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector)
555 {
451 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) 556 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
452 return; 557 return;
453 558
@@ -458,35 +563,42 @@ namespace OpenSim.Region.ScriptEngine.XEngine
458 563
459 if (cmdparams.Length == 2) 564 if (cmdparams.Length == 2)
460 { 565 {
461 foreach (IScriptInstance instance in m_Scripts.Values) 566 IEnumerable<IScriptInstance> scripts = m_Scripts.Values;
567
568 if (keySelector != null)
569 scripts = scripts.OrderBy<IScriptInstance, TKey>(keySelector);
570
571 foreach (IScriptInstance instance in scripts)
462 action(instance); 572 action(instance);
463 573
464 return; 574 return;
465 } 575 }
466 576
467 rawItemId = cmdparams[2]; 577 for (int i = 2; i < cmdparams.Length; i++)
468
469 if (!UUID.TryParse(rawItemId, out itemId))
470 {
471 MainConsole.Instance.OutputFormat("Error - {0} is not a valid UUID", rawItemId);
472 return;
473 }
474
475 if (itemId != UUID.Zero)
476 { 578 {
477 IScriptInstance instance = GetInstance(itemId); 579 rawItemId = cmdparams[i];
478 if (instance == null) 580
581 if (!UUID.TryParse(rawItemId, out itemId))
479 { 582 {
480 // Commented out for now since this will cause false reports on simulators with more than 583 MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid UUID", rawItemId);
481 // one scene where the current command line set region is 'root' (which causes commands to 584 continue;
482 // go to both regions... (sigh)
483// MainConsole.Instance.OutputFormat("Error - No item found with id {0}", itemId);
484 return;
485 } 585 }
486 else 586
587 if (itemId != UUID.Zero)
487 { 588 {
488 action(instance); 589 IScriptInstance instance = GetInstance(itemId);
489 return; 590 if (instance == null)
591 {
592 // Commented out for now since this will cause false reports on simulators with more than
593 // one scene where the current command line set region is 'root' (which causes commands to
594 // go to both regions... (sigh)
595 // MainConsole.Instance.OutputFormat("Error - No item found with id {0}", itemId);
596 continue;
597 }
598 else
599 {
600 action(instance);
601 }
490 } 602 }
491 } 603 }
492 } 604 }
@@ -505,9 +617,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
505 StringBuilder sb = new StringBuilder(); 617 StringBuilder sb = new StringBuilder();
506 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); 618 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName);
507 619
620 long scriptsLoaded, eventsQueued = 0, eventsProcessed = 0;
621
508 lock (m_Scripts) 622 lock (m_Scripts)
509 sb.AppendFormat("Scripts loaded : {0}\n", m_Scripts.Count); 623 {
624 scriptsLoaded = m_Scripts.Count;
510 625
626 foreach (IScriptInstance si in m_Scripts.Values)
627 {
628 eventsQueued += si.EventsQueued;
629 eventsProcessed += si.EventsProcessed;
630 }
631 }
632
633 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
511 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); 634 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
512 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); 635 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
513 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); 636 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
@@ -516,6 +639,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
516 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); 639 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads);
517 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); 640 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks);
518// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); 641// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count);
642 sb.AppendFormat("Events queued : {0}\n", eventsQueued);
643 sb.AppendFormat("Events processed : {0}\n", eventsProcessed);
519 644
520 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this); 645 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this);
521 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0); 646 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0);
@@ -546,7 +671,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
546 } 671 }
547 } 672 }
548 673
549 HandleScriptsAction(cmdparams, HandleShowScript); 674 HandleScriptsAction<long>(cmdparams, HandleShowScript, si => si.EventsProcessed);
550 } 675 }
551 676
552 private void HandleShowScript(IScriptInstance instance) 677 private void HandleShowScript(IScriptInstance instance)
@@ -572,15 +697,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
572 } 697 }
573 698
574 StringBuilder sb = new StringBuilder(); 699 StringBuilder sb = new StringBuilder();
575 Queue eq = instance.EventQueue;
576 700
577 sb.AppendFormat("Script name : {0}\n", instance.ScriptName); 701 sb.AppendFormat("Script name : {0}\n", instance.ScriptName);
578 sb.AppendFormat("Status : {0}\n", status); 702 sb.AppendFormat("Status : {0}\n", status);
579 703 sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
580 lock (eq) 704 sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
581 sb.AppendFormat("Queued events : {0}\n", eq.Count);
582
583 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); 705 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
706 sb.AppendFormat("Asset UUID : {0}\n", instance.AssetID);
584 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); 707 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
585 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); 708 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
586 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); 709 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition);
@@ -1079,7 +1202,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1079 } 1202 }
1080 1203
1081 m_log.DebugFormat( 1204 m_log.DebugFormat(
1082 "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1205 "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1083 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1206 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1084 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1207 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1085 1208
@@ -1089,8 +1212,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1089 1212
1090 string assembly = ""; 1213 string assembly = "";
1091 1214
1092 CultureInfo USCulture = new CultureInfo("en-US"); 1215 Culture.SetCurrentCulture();
1093 Thread.CurrentThread.CurrentCulture = USCulture;
1094 1216
1095 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap; 1217 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap;
1096 1218
@@ -1101,6 +1223,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1101 lock (m_AddingAssemblies) 1223 lock (m_AddingAssemblies)
1102 { 1224 {
1103 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap); 1225 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap);
1226
1104 if (!m_AddingAssemblies.ContainsKey(assembly)) { 1227 if (!m_AddingAssemblies.ContainsKey(assembly)) {
1105 m_AddingAssemblies[assembly] = 1; 1228 m_AddingAssemblies[assembly] = 1;
1106 } else { 1229 } else {
@@ -1150,7 +1273,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1150 } 1273 }
1151 catch (Exception e) 1274 catch (Exception e)
1152 { 1275 {
1153// m_log.ErrorFormat("[XEngine]: Exception when rezzing script {0}{1}", e.Message, e.StackTrace); 1276// m_log.ErrorFormat(
1277// "[XEngine]: Exception when rezzing script with item ID {0}, {1}{2}",
1278// itemID, e.Message, e.StackTrace);
1154 1279
1155 // try 1280 // try
1156 // { 1281 // {
@@ -1229,13 +1354,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1229 sandbox = AppDomain.CurrentDomain; 1354 sandbox = AppDomain.CurrentDomain;
1230 } 1355 }
1231 1356
1232 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1357 if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource))
1233 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1358 return false;
1234 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1235 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1236 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1237 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1238 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1239 1359
1240 m_AppDomains[appDomain] = sandbox; 1360 m_AppDomains[appDomain] = sandbox;
1241 1361
@@ -1256,12 +1376,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1256 m_DomainScripts[appDomain].Add(itemID); 1376 m_DomainScripts[appDomain].Add(itemID);
1257 1377
1258 instance = new ScriptInstance(this, part, 1378 instance = new ScriptInstance(this, part,
1259 itemID, assetID, assembly, 1379 item,
1260 m_AppDomains[appDomain], 1380 startParam, postOnRez,
1261 part.ParentGroup.RootPart.Name, 1381 m_MaxScriptQueue);
1262 item.Name, startParam, postOnRez,
1263 stateSource, m_MaxScriptQueue);
1264 1382
1383 instance.Load(m_AppDomains[appDomain], assembly, stateSource);
1265// m_log.DebugFormat( 1384// m_log.DebugFormat(
1266// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 1385// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1267// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 1386// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
@@ -1347,9 +1466,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1347 lockScriptsForWrite(false); 1466 lockScriptsForWrite(false);
1348 instance.ClearQueue(); 1467 instance.ClearQueue();
1349 1468
1350 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1469 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1351 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1352 instance.Stop(1000);
1353 1470
1354// bool objectRemoved = false; 1471// bool objectRemoved = false;
1355 1472
@@ -1477,7 +1594,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1477 m_MaxScriptQueue = maxScriptQueue; 1594 m_MaxScriptQueue = maxScriptQueue;
1478 1595
1479 STPStartInfo startInfo = new STPStartInfo(); 1596 STPStartInfo startInfo = new STPStartInfo();
1480 startInfo.IdleTimeout = idleTimeout*1000; // convert to seconds as stated in .ini 1597 startInfo.ThreadPoolName = "XEngine";
1598 startInfo.IdleTimeout = idleTimeout * 1000; // convert to seconds as stated in .ini
1481 startInfo.MaxWorkerThreads = maxThreads; 1599 startInfo.MaxWorkerThreads = maxThreads;
1482 startInfo.MinWorkerThreads = minThreads; 1600 startInfo.MinWorkerThreads = minThreads;
1483 startInfo.ThreadPriority = threadPriority;; 1601 startInfo.ThreadPriority = threadPriority;;
@@ -1504,8 +1622,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1504 /// <returns></returns> 1622 /// <returns></returns>
1505 private object ProcessEventHandler(object parms) 1623 private object ProcessEventHandler(object parms)
1506 { 1624 {
1507 CultureInfo USCulture = new CultureInfo("en-US"); 1625 Culture.SetCurrentCulture();
1508 Thread.CurrentThread.CurrentCulture = USCulture;
1509 1626
1510 IScriptInstance instance = (ScriptInstance) parms; 1627 IScriptInstance instance = (ScriptInstance) parms;
1511 1628
@@ -1693,7 +1810,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1693 { 1810 {
1694 IScriptInstance instance = GetInstance(itemID); 1811 IScriptInstance instance = GetInstance(itemID);
1695 if (instance != null) 1812 if (instance != null)
1696 instance.ResetScript(); 1813 instance.ResetScript(m_WaitForEventCompletionOnScriptStop);
1697 } 1814 }
1698 1815
1699 public void StartScript(UUID itemID) 1816 public void StartScript(UUID itemID)
@@ -1708,14 +1825,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1708 public void StopScript(UUID itemID) 1825 public void StopScript(UUID itemID)
1709 { 1826 {
1710 IScriptInstance instance = GetInstance(itemID); 1827 IScriptInstance instance = GetInstance(itemID);
1828
1711 if (instance != null) 1829 if (instance != null)
1712 { 1830 {
1713 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1831 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1714 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1715 instance.Stop(1000);
1716 } 1832 }
1717 else 1833 else
1718 { 1834 {
1835// m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name);
1719 m_runFlags.AddOrUpdate(itemID, false, 240); 1836 m_runFlags.AddOrUpdate(itemID, false, 240);
1720 } 1837 }
1721 } 1838 }
diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
index 3243a9a..6a1112c 100644
--- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32using System.Text; 32using System.Text;
33using Mono.Data.SqliteClient; 33using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework.Monitoring; 38using OpenSim.Framework.Monitoring;
@@ -51,7 +52,6 @@ namespace OpenSim.Region.UserStatistics
51 52
52 public Hashtable ProcessModel(Hashtable pParams) 53 public Hashtable ProcessModel(Hashtable pParams)
53 { 54 {
54
55 List<Scene> m_scene = (List<Scene>)pParams["Scenes"]; 55 List<Scene> m_scene = (List<Scene>)pParams["Scenes"];
56 56
57 Hashtable nh = new Hashtable(); 57 Hashtable nh = new Hashtable();
@@ -129,6 +129,86 @@ namespace OpenSim.Region.UserStatistics
129 return output.ToString(); 129 return output.ToString();
130 } 130 }
131 131
132 /// <summary>
133 /// Convert active connections information to JSON string. Returns a structure:
134 /// <pre>
135 /// {"regionName": {
136 /// "presenceName": {
137 /// "name": "presenceName",
138 /// "position": "<x,y,z>",
139 /// "isRoot": "false",
140 /// "throttle": {
141 /// },
142 /// "queue": {
143 /// }
144 /// },
145 /// ... // multiple presences in the scene
146 /// },
147 /// ... // multiple regions in the sim
148 /// }
149 ///
150 /// </pre>
151 /// </summary>
152 /// <param name="pModelResult"></param>
153 /// <returns></returns>
154 public string RenderJson(Hashtable pModelResult)
155 {
156 List<Scene> all_scenes = (List<Scene>) pModelResult["hdata"];
157
158 OSDMap regionInfo = new OSDMap();
159 foreach (Scene scene in all_scenes)
160 {
161 OSDMap sceneInfo = new OpenMetaverse.StructuredData.OSDMap();
162 List<ScenePresence> avatarInScene = scene.GetScenePresences();
163 foreach (ScenePresence av in avatarInScene)
164 {
165 OSDMap presenceInfo = new OSDMap();
166 presenceInfo.Add("Name", new OSDString(av.Name));
167
168 Dictionary<string,string> queues = new Dictionary<string, string>();
169 if (av.ControllingClient is IStatsCollector)
170 {
171 IStatsCollector isClient = (IStatsCollector) av.ControllingClient;
172 queues = decodeQueueReport(isClient.Report());
173 }
174 OSDMap queueInfo = new OpenMetaverse.StructuredData.OSDMap();
175 foreach (KeyValuePair<string, string> kvp in queues) {
176 queueInfo.Add(kvp.Key, new OSDString(kvp.Value));
177 }
178 sceneInfo.Add("queues", queueInfo);
179
180 if (av.IsChildAgent)
181 presenceInfo.Add("isRoot", new OSDString("false"));
182 else
183 presenceInfo.Add("isRoot", new OSDString("true"));
184
185 if (av.AbsolutePosition == DefaultNeighborPosition)
186 {
187 presenceInfo.Add("position", new OSDString("<0, 0, 0>"));
188 }
189 else
190 {
191 presenceInfo.Add("position", new OSDString(string.Format("<{0},{1},{2}>",
192 (int)av.AbsolutePosition.X,
193 (int) av.AbsolutePosition.Y,
194 (int) av.AbsolutePosition.Z)) );
195 }
196
197 Dictionary<string, int> throttles = DecodeClientThrottles(av.ControllingClient.GetThrottlesPacked(1));
198 OSDMap throttleInfo = new OpenMetaverse.StructuredData.OSDMap();
199 foreach (string throttlename in throttles.Keys)
200 {
201 throttleInfo.Add(throttlename, new OSDString(throttles[throttlename].ToString()));
202 }
203 presenceInfo.Add("throttle", throttleInfo);
204
205 sceneInfo.Add(av.Name, presenceInfo);
206 }
207 regionInfo.Add(scene.RegionInfo.RegionName, sceneInfo);
208 }
209 return regionInfo.ToString();
210 }
211
132 public Dictionary<string, int> DecodeClientThrottles(byte[] throttle) 212 public Dictionary<string, int> DecodeClientThrottles(byte[] throttle)
133 { 213 {
134 Dictionary<string, int> returndict = new Dictionary<string, int>(); 214 Dictionary<string, int> returndict = new Dictionary<string, int>();
@@ -203,7 +283,7 @@ namespace OpenSim.Region.UserStatistics
203 returndic.Add("Cloud", rep.Substring((7 * pos) , 8)); pos++; 283 returndic.Add("Cloud", rep.Substring((7 * pos) , 8)); pos++;
204 returndic.Add("Task", rep.Substring((7 * pos) , 8)); pos++; 284 returndic.Add("Task", rep.Substring((7 * pos) , 8)); pos++;
205 returndic.Add("Texture", rep.Substring((7 * pos), 8)); pos++; 285 returndic.Add("Texture", rep.Substring((7 * pos), 8)); pos++;
206 returndic.Add("Asset", rep.Substring((7 * pos), 8)); 286 returndic.Add("Asset", rep.Substring((7 * pos), 8));
207 /* 287 /*
208 * return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", 288 * return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
209 SendQueue.Count(), 289 SendQueue.Count(),
diff --git a/OpenSim/Region/UserStatistics/Clients_report.cs b/OpenSim/Region/UserStatistics/Clients_report.cs
index b2bb33b..4a6f7be 100644
--- a/OpenSim/Region/UserStatistics/Clients_report.cs
+++ b/OpenSim/Region/UserStatistics/Clients_report.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Text; 31using System.Text;
32using Mono.Data.SqliteClient; 32using Mono.Data.SqliteClient;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
34using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
35 36
36namespace OpenSim.Region.UserStatistics 37namespace OpenSim.Region.UserStatistics
@@ -44,6 +45,32 @@ namespace OpenSim.Region.UserStatistics
44 get { return "Client"; } 45 get { return "Client"; }
45 } 46 }
46 47
48 /// <summary>
49 /// Return summar information in the form:
50 /// <pre>
51 /// {"totalUsers": "34",
52 /// "totalSessions": "233",
53 /// ...
54 /// }
55 /// </pre>
56 /// </summary>
57 /// <param name="pModelResult"></param>
58 /// <returns></returns>
59 public string RenderJson(Hashtable pModelResult) {
60 stats_default_page_values values = (stats_default_page_values) pModelResult["hdata"];
61
62 OSDMap summaryInfo = new OpenMetaverse.StructuredData.OSDMap();
63 summaryInfo.Add("totalUsers", new OSDString(values.total_num_users.ToString()));
64 summaryInfo.Add("totalSessions", new OSDString(values.total_num_sessions.ToString()));
65 summaryInfo.Add("averageClientFPS", new OSDString(values.avg_client_fps.ToString()));
66 summaryInfo.Add("averageClientMem", new OSDString(values.avg_client_mem_use.ToString()));
67 summaryInfo.Add("averageSimFPS", new OSDString(values.avg_sim_fps.ToString()));
68 summaryInfo.Add("averagePingTime", new OSDString(values.avg_ping.ToString()));
69 summaryInfo.Add("totalKBOut", new OSDString(values.total_kb_out.ToString()));
70 summaryInfo.Add("totalKBIn", new OSDString(values.total_kb_in.ToString()));
71 return summaryInfo.ToString();
72 }
73
47 public Hashtable ProcessModel(Hashtable pParams) 74 public Hashtable ProcessModel(Hashtable pParams)
48 { 75 {
49 SqliteConnection dbConn = (SqliteConnection)pParams["DatabaseConnection"]; 76 SqliteConnection dbConn = (SqliteConnection)pParams["DatabaseConnection"];
diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/UserStatistics/Default_Report.cs
index cdc615c..fabe3d4 100644
--- a/OpenSim/Region/UserStatistics/Default_Report.cs
+++ b/OpenSim/Region/UserStatistics/Default_Report.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32using System.Text; 32using System.Text;
33using Mono.Data.SqliteClient; 33using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
35using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
36using OpenSim.Framework.Monitoring; 37using OpenSim.Framework.Monitoring;
37 38
@@ -230,6 +231,31 @@ TD.align_top { vertical-align: top; }
230 return returnstruct; 231 return returnstruct;
231 } 232 }
232 233
234 /// <summary>
235 /// Return summar information in the form:
236 /// <pre>
237 /// {"totalUsers": "34",
238 /// "totalSessions": "233",
239 /// ...
240 /// }
241 /// </pre>
242 /// </summary>
243 /// <param name="pModelResult"></param>
244 /// <returns></returns>
245 public string RenderJson(Hashtable pModelResult) {
246 stats_default_page_values values = (stats_default_page_values) pModelResult["hdata"];
247
248 OSDMap summaryInfo = new OSDMap();
249 summaryInfo.Add("totalUsers", new OSDString(values.total_num_users.ToString()));
250 summaryInfo.Add("totalSessions", new OSDString(values.total_num_sessions.ToString()));
251 summaryInfo.Add("averageClientFPS", new OSDString(values.avg_client_fps.ToString()));
252 summaryInfo.Add("averageClientMem", new OSDString(values.avg_client_mem_use.ToString()));
253 summaryInfo.Add("averageSimFPS", new OSDString(values.avg_sim_fps.ToString()));
254 summaryInfo.Add("averagePingTime", new OSDString(values.avg_ping.ToString()));
255 summaryInfo.Add("totalKBOut", new OSDString(values.total_kb_out.ToString()));
256 summaryInfo.Add("totalKBIn", new OSDString(values.total_kb_in.ToString()));
257 return summaryInfo.ToString();
258 }
233 } 259 }
234 260
235 public struct stats_default_page_values 261 public struct stats_default_page_values
@@ -247,4 +273,5 @@ TD.align_top { vertical-align: top; }
247 public Dictionary<UUID, USimStatsData> sim_stat_data; 273 public Dictionary<UUID, USimStatsData> sim_stat_data;
248 public Dictionary<string, IStatsController> stats_reports; 274 public Dictionary<string, IStatsController> stats_reports;
249 } 275 }
276
250} 277}
diff --git a/OpenSim/Region/UserStatistics/IStatsReport.cs b/OpenSim/Region/UserStatistics/IStatsReport.cs
index e0ecce4..80c4487 100644
--- a/OpenSim/Region/UserStatistics/IStatsReport.cs
+++ b/OpenSim/Region/UserStatistics/IStatsReport.cs
@@ -34,5 +34,6 @@ namespace OpenSim.Region.UserStatistics
34 string ReportName { get; } 34 string ReportName { get; }
35 Hashtable ProcessModel(Hashtable pParams); 35 Hashtable ProcessModel(Hashtable pParams);
36 string RenderView(Hashtable pModelResult); 36 string RenderView(Hashtable pModelResult);
37 string RenderJson(Hashtable pModelResult);
37 } 38 }
38} 39}
diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
index 74de46b..4d45b80 100644
--- a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
+++ b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
@@ -33,6 +33,7 @@ using System.Text;
33using System.Text.RegularExpressions; 33using System.Text.RegularExpressions;
34using Mono.Data.SqliteClient; 34using Mono.Data.SqliteClient;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework.Monitoring; 38using OpenSim.Framework.Monitoring;
38 39
@@ -125,6 +126,34 @@ namespace OpenSim.Region.UserStatistics
125 return output.ToString(); 126 return output.ToString();
126 } 127 }
127 128
129 /// <summary>
130 /// Return the last log lines. Output in the format:
131 /// <pre>
132 /// {"logLines": [
133 /// "line1",
134 /// "line2",
135 /// ...
136 /// ]
137 /// }
138 /// </pre>
139 /// </summary>
140 /// <param name="pModelResult"></param>
141 /// <returns></returns>
142 public string RenderJson(Hashtable pModelResult)
143 {
144 OSDMap logInfo = new OpenMetaverse.StructuredData.OSDMap();
145
146 OSDArray logLines = new OpenMetaverse.StructuredData.OSDArray();
147 string tmp = normalizeEndLines.Replace(pModelResult["loglines"].ToString(), "\n");
148 string[] result = Regex.Split(tmp, "\n");
149 for (int i = 0; i < result.Length; i++)
150 {
151 logLines.Add(new OSDString(result[i]));
152 }
153 logInfo.Add("logLines", logLines);
154 return logInfo.ToString();
155 }
156
128 #endregion 157 #endregion
129 } 158 }
130} 159}
diff --git a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
index 100cf99..caa6d4e 100644
--- a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/UserStatistics/Prototype_distributor.cs b/OpenSim/Region/UserStatistics/Prototype_distributor.cs
index 53ae557..6f8b2aa 100644
--- a/OpenSim/Region/UserStatistics/Prototype_distributor.cs
+++ b/OpenSim/Region/UserStatistics/Prototype_distributor.cs
@@ -36,7 +36,18 @@ namespace OpenSim.Region.UserStatistics
36{ 36{
37 public class Prototype_distributor : IStatsController 37 public class Prototype_distributor : IStatsController
38 { 38 {
39 private string prototypejs=string.Empty; 39 private string jsFileName = "prototype.js";
40 private string prototypejs = string.Empty;
41
42 public Prototype_distributor()
43 {
44 jsFileName = "prototype.js";
45 }
46
47 public Prototype_distributor(string jsName)
48 {
49 jsFileName = jsName;
50 }
40 51
41 public string ReportName 52 public string ReportName
42 { 53 {
@@ -45,20 +56,24 @@ namespace OpenSim.Region.UserStatistics
45 public Hashtable ProcessModel(Hashtable pParams) 56 public Hashtable ProcessModel(Hashtable pParams)
46 { 57 {
47 Hashtable pResult = new Hashtable(); 58 Hashtable pResult = new Hashtable();
48 if (prototypejs.Length == 0) 59 pResult["js"] = jsFileName;
60 return pResult;
61 }
62
63 public string RenderView(Hashtable pModelResult)
64 {
65 string fileName = (string)pModelResult["js"];
66 using (StreamReader fs = new StreamReader(new FileStream(Util.dataDir() + "/data/" + fileName, FileMode.Open)))
49 { 67 {
50 StreamReader fs = new StreamReader(new FileStream(Util.dataDir() + "/data/prototype.js", FileMode.Open));
51 prototypejs = fs.ReadToEnd(); 68 prototypejs = fs.ReadToEnd();
52 fs.Close(); 69 fs.Close();
53 fs.Dispose();
54 } 70 }
55 pResult["js"] = prototypejs; 71 return prototypejs;
56 return pResult;
57 } 72 }
58 73
59 public string RenderView(Hashtable pModelResult) 74 public string RenderJson(Hashtable pModelResult)
60 { 75 {
61 return pModelResult["js"].ToString(); 76 return "{}";
62 } 77 }
63 78
64 } 79 }
diff --git a/OpenSim/Region/UserStatistics/Sessions_Report.cs b/OpenSim/Region/UserStatistics/Sessions_Report.cs
index 1a2d460..0e94912 100644
--- a/OpenSim/Region/UserStatistics/Sessions_Report.cs
+++ b/OpenSim/Region/UserStatistics/Sessions_Report.cs
@@ -278,6 +278,11 @@ TD.align_top { vertical-align: top; }
278 public DateTime start_time; 278 public DateTime start_time;
279 } 279 }
280 280
281 public string RenderJson(Hashtable pModelResult)
282 {
283 return "{}";
284 }
281 #endregion 285 #endregion
282 } 286 }
287
283} 288}
diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
index 28051fb..ad848a1 100644
--- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32using System.Text; 32using System.Text;
33using Mono.Data.SqliteClient; 33using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
35using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
36using OpenSim.Framework.Monitoring; 37using OpenSim.Framework.Monitoring;
37 38
@@ -218,6 +219,64 @@ namespace OpenSim.Region.UserStatistics
218 return output.ToString(); 219 return output.ToString();
219 } 220 }
220 221
222 /// <summary>
223 /// Return stat information for all regions in the sim. Returns data of the form:
224 /// <pre>
225 /// {"REGIONNAME": {
226 /// "region": "REGIONNAME",
227 /// "timeDilation": "101",
228 /// ... // the rest of the stat info
229 /// },
230 /// ... // entries for each region
231 /// }
232 /// </pre>
233 /// </summary>
234 /// <param name="pModelResult"></param>
235 /// <returns></returns>
236 public string RenderJson(Hashtable pModelResult)
237 {
238 List<Scene> all_scenes = (List<Scene>) pModelResult["hdata"];
239 Dictionary<UUID, USimStatsData> sdatadic = (Dictionary<UUID,USimStatsData>)pModelResult["simstats"];
240
241 OSDMap allStatsInfo = new OpenMetaverse.StructuredData.OSDMap();
242 foreach (USimStatsData sdata in sdatadic.Values)
243 {
244 OSDMap statsInfo = new OpenMetaverse.StructuredData.OSDMap();
245 string regionName = "unknown";
246 foreach (Scene sn in all_scenes)
247 {
248 if (sn.RegionInfo.RegionID == sdata.RegionId)
249 {
250 regionName = sn.RegionInfo.RegionName;
251 break;
252 }
253 }
254 statsInfo.Add("region", new OSDString(regionName));
255 statsInfo.Add("timeDilation", new OSDString(sdata.TimeDilation.ToString()));
256 statsInfo.Add("simFPS", new OSDString(sdata.SimFps.ToString()));
257 statsInfo.Add("physicsFPS", new OSDString(sdata.PhysicsFps.ToString()));
258 statsInfo.Add("agentUpdates", new OSDString(sdata.AgentUpdates.ToString()));
259 statsInfo.Add("rootAgents", new OSDString(sdata.RootAgents.ToString()));
260 statsInfo.Add("childAgents", new OSDString(sdata.ChildAgents.ToString()));
261 statsInfo.Add("totalPrims", new OSDString(sdata.TotalPrims.ToString()));
262 statsInfo.Add("activePrims", new OSDString(sdata.ActivePrims.ToString()));
263 statsInfo.Add("activeScripts", new OSDString(sdata.ActiveScripts.ToString()));
264 statsInfo.Add("scriptLinesPerSec", new OSDString(sdata.ScriptLinesPerSecond.ToString()));
265 statsInfo.Add("totalFrameTime", new OSDString(sdata.TotalFrameTime.ToString()));
266 statsInfo.Add("agentFrameTime", new OSDString(sdata.AgentFrameTime.ToString()));
267 statsInfo.Add("physicsFrameTime", new OSDString(sdata.PhysicsFrameTime.ToString()));
268 statsInfo.Add("otherFrameTime", new OSDString(sdata.OtherFrameTime.ToString()));
269 statsInfo.Add("outPacketsPerSec", new OSDString(sdata.OutPacketsPerSecond.ToString()));
270 statsInfo.Add("inPacketsPerSec", new OSDString(sdata.InPacketsPerSecond.ToString()));
271 statsInfo.Add("unackedByptes", new OSDString(sdata.UnackedBytes.ToString()));
272 statsInfo.Add("pendingDownloads", new OSDString(sdata.PendingDownloads.ToString()));
273 statsInfo.Add("pendingUploads", new OSDString(sdata.PendingUploads.ToString()));
274
275 allStatsInfo.Add(regionName, statsInfo);
276 }
277 return allStatsInfo.ToString();
278 }
279
221 #endregion 280 #endregion
222 } 281 }
223} 282}
diff --git a/OpenSim/Region/UserStatistics/Updater_distributor.cs b/OpenSim/Region/UserStatistics/Updater_distributor.cs
index 9593cc9..601e06b 100644
--- a/OpenSim/Region/UserStatistics/Updater_distributor.cs
+++ b/OpenSim/Region/UserStatistics/Updater_distributor.cs
@@ -62,5 +62,9 @@ namespace OpenSim.Region.UserStatistics
62 return pModelResult["js"].ToString(); 62 return pModelResult["js"].ToString();
63 } 63 }
64 64
65 public string RenderJson(Hashtable pModelResult) {
66 return "{}";
67 }
68
65 } 69 }
66} \ No newline at end of file 70} \ No newline at end of file
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
index b08233c..b98b762 100644
--- a/OpenSim/Region/UserStatistics/WebStatsModule.cs
+++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs
@@ -94,8 +94,6 @@ namespace OpenSim.Region.UserStatistics
94 if (!enabled) 94 if (!enabled)
95 return; 95 return;
96 96
97 AddEventHandlers();
98
99 if (Util.IsWindows()) 97 if (Util.IsWindows())
100 Util.LoadArchSpecificWindowsDll("sqlite3.dll"); 98 Util.LoadArchSpecificWindowsDll("sqlite3.dll");
101 99
@@ -123,6 +121,10 @@ namespace OpenSim.Region.UserStatistics
123 reports.Add("clients.report", clientReport); 121 reports.Add("clients.report", clientReport);
124 reports.Add("sessions.report", sessionsReport); 122 reports.Add("sessions.report", sessionsReport);
125 123
124 reports.Add("sim.css", new Prototype_distributor("sim.css"));
125 reports.Add("sim.html", new Prototype_distributor("sim.html"));
126 reports.Add("jquery.js", new Prototype_distributor("jquery.js"));
127
126 //// 128 ////
127 // Add Your own Reports here (Do Not Modify Lines here Devs!) 129 // Add Your own Reports here (Do Not Modify Lines here Devs!)
128 //// 130 ////
@@ -143,10 +145,14 @@ namespace OpenSim.Region.UserStatistics
143 lock (m_scenes) 145 lock (m_scenes)
144 { 146 {
145 m_scenes.Add(scene); 147 m_scenes.Add(scene);
146 if (m_simstatsCounters.ContainsKey(scene.RegionInfo.RegionID)) 148 updateLogMod = m_scenes.Count * 2;
147 m_simstatsCounters.Remove(scene.RegionInfo.RegionID);
148 149
149 m_simstatsCounters.Add(scene.RegionInfo.RegionID, new USimStatsData(scene.RegionInfo.RegionID)); 150 m_simstatsCounters.Add(scene.RegionInfo.RegionID, new USimStatsData(scene.RegionInfo.RegionID));
151
152 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
153 scene.EventManager.OnDeregisterCaps += OnDeRegisterCaps;
154 scene.EventManager.OnClientClosed += OnClientClosed;
155 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
150 scene.StatsReporter.OnSendStatsResult += ReceiveClassicSimStatsPacket; 156 scene.StatsReporter.OnSendStatsResult += ReceiveClassicSimStatsPacket;
151 } 157 }
152 } 158 }
@@ -157,6 +163,15 @@ namespace OpenSim.Region.UserStatistics
157 163
158 public void RemoveRegion(Scene scene) 164 public void RemoveRegion(Scene scene)
159 { 165 {
166 if (!enabled)
167 return;
168
169 lock (m_scenes)
170 {
171 m_scenes.Remove(scene);
172 updateLogMod = m_scenes.Count * 2;
173 m_simstatsCounters.Remove(scene.RegionInfo.RegionID);
174 }
160 } 175 }
161 176
162 public virtual void Close() 177 public virtual void Close()
@@ -187,9 +202,7 @@ namespace OpenSim.Region.UserStatistics
187 private void ReceiveClassicSimStatsPacket(SimStats stats) 202 private void ReceiveClassicSimStatsPacket(SimStats stats)
188 { 203 {
189 if (!enabled) 204 if (!enabled)
190 {
191 return; 205 return;
192 }
193 206
194 try 207 try
195 { 208 {
@@ -198,17 +211,25 @@ namespace OpenSim.Region.UserStatistics
198 if (concurrencyCounter > 0 || System.Environment.TickCount - lastHit > 30000) 211 if (concurrencyCounter > 0 || System.Environment.TickCount - lastHit > 30000)
199 return; 212 return;
200 213
201 if ((updateLogCounter++ % updateLogMod) == 0) 214 // We will conduct this under lock so that fields such as updateLogCounter do not potentially get
215 // confused if a scene is removed.
216 // XXX: Possibly the scope of this lock could be reduced though it's not critical.
217 lock (m_scenes)
202 { 218 {
203 m_loglines = readLogLines(10); 219 if (updateLogMod != 0 && updateLogCounter++ % updateLogMod == 0)
204 if (updateLogCounter > 10000) updateLogCounter = 1; 220 {
205 } 221 m_loglines = readLogLines(10);
222
223 if (updateLogCounter > 10000)
224 updateLogCounter = 1;
225 }
206 226
207 USimStatsData ss = m_simstatsCounters[stats.RegionUUID]; 227 USimStatsData ss = m_simstatsCounters[stats.RegionUUID];
208 228
209 if ((++ss.StatsCounter % updateStatsMod) == 0) 229 if ((++ss.StatsCounter % updateStatsMod) == 0)
210 { 230 {
211 ss.ConsumeSimStats(stats); 231 ss.ConsumeSimStats(stats);
232 }
212 } 233 }
213 } 234 }
214 catch (KeyNotFoundException) 235 catch (KeyNotFoundException)
@@ -238,9 +259,12 @@ namespace OpenSim.Region.UserStatistics
238 string regpath = request["uri"].ToString(); 259 string regpath = request["uri"].ToString();
239 int response_code = 404; 260 int response_code = 404;
240 string contenttype = "text/html"; 261 string contenttype = "text/html";
262 bool jsonFormatOutput = false;
241 263
242 string strOut = string.Empty; 264 string strOut = string.Empty;
243 265
266 // The request patch should be "/SStats/reportName" where 'reportName'
267 // is one of the names added to the 'reports' hashmap.
244 regpath = regpath.Remove(0, 8); 268 regpath = regpath.Remove(0, 8);
245 if (regpath.Length == 0) regpath = "default.report"; 269 if (regpath.Length == 0) regpath = "default.report";
246 if (reports.ContainsKey(regpath)) 270 if (reports.ContainsKey(regpath))
@@ -248,6 +272,9 @@ namespace OpenSim.Region.UserStatistics
248 IStatsController rep = reports[regpath]; 272 IStatsController rep = reports[regpath];
249 Hashtable repParams = new Hashtable(); 273 Hashtable repParams = new Hashtable();
250 274
275 if (request.ContainsKey("json"))
276 jsonFormatOutput = true;
277
251 if (request.ContainsKey("requestvars")) 278 if (request.ContainsKey("requestvars"))
252 repParams["RequestVars"] = request["requestvars"]; 279 repParams["RequestVars"] = request["requestvars"];
253 else 280 else
@@ -267,13 +294,26 @@ namespace OpenSim.Region.UserStatistics
267 294
268 concurrencyCounter++; 295 concurrencyCounter++;
269 296
270 strOut = rep.RenderView(rep.ProcessModel(repParams)); 297 if (jsonFormatOutput)
298 {
299 strOut = rep.RenderJson(rep.ProcessModel(repParams));
300 contenttype = "text/json";
301 }
302 else
303 {
304 strOut = rep.RenderView(rep.ProcessModel(repParams));
305 }
271 306
272 if (regpath.EndsWith("js")) 307 if (regpath.EndsWith("js"))
273 { 308 {
274 contenttype = "text/javascript"; 309 contenttype = "text/javascript";
275 } 310 }
276 311
312 if (regpath.EndsWith("css"))
313 {
314 contenttype = "text/css";
315 }
316
277 concurrencyCounter--; 317 concurrencyCounter--;
278 318
279 response_code = 200; 319 response_code = 200;
@@ -380,7 +420,7 @@ namespace OpenSim.Region.UserStatistics
380 Encoding encoding = Encoding.ASCII; 420 Encoding encoding = Encoding.ASCII;
381 int sizeOfChar = encoding.GetByteCount("\n"); 421 int sizeOfChar = encoding.GetByteCount("\n");
382 byte[] buffer = encoding.GetBytes("\n"); 422 byte[] buffer = encoding.GetBytes("\n");
383 string logfile = Util.logDir() + "/" + "OpenSim.log"; 423 string logfile = Util.logFile();
384 FileStream fs = new FileStream(logfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 424 FileStream fs = new FileStream(logfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
385 Int64 tokenCount = 0; 425 Int64 tokenCount = 0;
386 Int64 endPosition = fs.Length / sizeOfChar; 426 Int64 endPosition = fs.Length / sizeOfChar;
diff --git a/OpenSim/Server/Base/CommandManager.cs b/OpenSim/Server/Base/CommandManager.cs
new file mode 100644
index 0000000..bd18485
--- /dev/null
+++ b/OpenSim/Server/Base/CommandManager.cs
@@ -0,0 +1,359 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28
29using System;
30using System.Text;
31using System.Linq;
32using System.Collections;
33using System.Collections.Generic;
34using System.Collections.ObjectModel;
35using Mono.Addins.Setup;
36using Mono.Addins;
37using Mono.Addins.Description;
38using OpenSim.Framework;
39
40namespace OpenSim.Server.Base
41{
42 /// <summary>
43 /// Command manager -
44 /// Wrapper for OpenSim.Framework.PluginManager to allow
45 /// us to add commands to the console to perform operations
46 /// on our repos and plugins
47 /// </summary>
48 public class CommandManager
49 {
50 public AddinRegistry PluginRegistry;
51 protected PluginManager PluginManager;
52
53 public CommandManager(AddinRegistry registry)
54 {
55 PluginRegistry = registry;
56 PluginManager = new PluginManager(PluginRegistry);
57 AddManagementCommands();
58 }
59
60 private void AddManagementCommands()
61 {
62 // add plugin
63 MainConsole.Instance.Commands.AddCommand("Plugin", true,
64 "plugin add", "plugin add \"plugin index\"",
65 "Install plugin from repository.",
66 HandleConsoleInstallPlugin);
67
68 // remove plugin
69 MainConsole.Instance.Commands.AddCommand("Plugin", true,
70 "plugin remove", "plugin remove \"plugin index\"",
71 "Remove plugin from repository",
72 HandleConsoleUnInstallPlugin);
73
74 // list installed plugins
75 MainConsole.Instance.Commands.AddCommand("Plugin", true,
76 "plugin list installed",
77 "plugin list installed","List install plugins",
78 HandleConsoleListInstalledPlugin);
79
80 // list plugins available from registered repositories
81 MainConsole.Instance.Commands.AddCommand("Plugin", true,
82 "plugin list available",
83 "plugin list available","List available plugins",
84 HandleConsoleListAvailablePlugin);
85 // List available updates
86 MainConsole.Instance.Commands.AddCommand("Plugin", true,
87 "plugin updates", "plugin updates","List availble updates",
88 HandleConsoleListUpdates);
89
90 // Update plugin
91 MainConsole.Instance.Commands.AddCommand("Plugin", true,
92 "plugin update", "plugin update \"plugin index\"","Update the plugin",
93 HandleConsoleUpdatePlugin);
94
95 // Add repository
96 MainConsole.Instance.Commands.AddCommand("Repository", true,
97 "repo add", "repo add \"url\"","Add repository",
98 HandleConsoleAddRepo);
99
100 // Refresh repo
101 MainConsole.Instance.Commands.AddCommand("Repository", true,
102 "repo refresh", "repo refresh \"url\"", "Sync with a registered repository",
103 HandleConsoleGetRepo);
104
105 // Remove repository from registry
106 MainConsole.Instance.Commands.AddCommand("Repository", true,
107 "repo remove",
108 "repo remove \"[url | index]\"",
109 "Remove repository from registry",
110 HandleConsoleRemoveRepo);
111
112 // Enable repo
113 MainConsole.Instance.Commands.AddCommand("Repository", true,
114 "repo enable", "repo enable \"[url | index]\"",
115 "Enable registered repository",
116 HandleConsoleEnableRepo);
117
118 // Disable repo
119 MainConsole.Instance.Commands.AddCommand("Repository", true,
120 "repo disable", "repo disable\"[url | index]\"",
121 "Disable registered repository",
122 HandleConsoleDisableRepo);
123
124 // List registered repositories
125 MainConsole.Instance.Commands.AddCommand("Repository", true,
126 "repo list", "repo list",
127 "List registered repositories",
128 HandleConsoleListRepos);
129
130 // *
131 MainConsole.Instance.Commands.AddCommand("Plugin", true,
132 "plugin info", "plugin info \"plugin index\"","Show detailed information for plugin",
133 HandleConsoleShowAddinInfo);
134
135 // Plugin disable
136 MainConsole.Instance.Commands.AddCommand("Plugin", true,
137 "plugin disable", "plugin disable \"plugin index\"",
138 "Disable a plugin",
139 HandleConsoleDisablePlugin);
140
141 // Enable plugin
142 MainConsole.Instance.Commands.AddCommand("Plugin", true,
143 "plugin enable", "plugin enable \"plugin index\"",
144 "Enable the selected plugin plugin",
145 HandleConsoleEnablePlugin);
146 }
147
148 #region console handlers
149 // Handle our console commands
150 //
151 // Install plugin from registered repository
152 /// <summary>
153 /// Handles the console install plugin command. Attempts to install the selected plugin
154 /// and
155 /// </summary>
156 /// <param name='module'>
157 /// Module.
158 /// </param>
159 /// <param name='cmd'>
160 /// Cmd.
161 /// </param>
162 private void HandleConsoleInstallPlugin(string module, string[] cmd)
163 {
164 Dictionary<string, object> result = new Dictionary<string, object>();
165
166 if (cmd.Length == 3)
167 {
168 int ndx = Convert.ToInt16(cmd[2]);
169 if (PluginManager.InstallPlugin(ndx, out result) == true)
170 {
171 ArrayList s = new ArrayList();
172 s.AddRange(result.Keys);
173 s.Sort();
174
175 var list = result.Keys.ToList();
176 list.Sort();
177 foreach (var k in list)
178 {
179 Dictionary<string, object> plugin = (Dictionary<string, object>)result[k];
180 bool enabled = (bool)plugin["enabled"];
181 MainConsole.Instance.OutputFormat("{0}) {1} {2} rev. {3}",
182 k,
183 enabled == true ? "[ ]" : "[X]",
184 plugin["name"], plugin["version"]);
185 }
186 }
187 }
188 return;
189 }
190
191 // Remove installed plugin
192 private void HandleConsoleUnInstallPlugin(string module, string[] cmd)
193 {
194 if (cmd.Length == 3)
195 {
196 int ndx = Convert.ToInt16(cmd[2]);
197 PluginManager.UnInstall(ndx);
198 }
199 return;
200 }
201
202 // List installed plugins
203 private void HandleConsoleListInstalledPlugin(string module, string[] cmd)
204 {
205 Dictionary<string, object> result = new Dictionary<string, object>();
206 PluginManager.ListInstalledAddins(out result);
207
208 ArrayList s = new ArrayList();
209 s.AddRange(result.Keys);
210 s.Sort();
211
212 var list = result.Keys.ToList();
213 list.Sort();
214 foreach (var k in list)
215 {
216 Dictionary<string, object> plugin = (Dictionary<string, object>)result[k];
217 bool enabled = (bool)plugin["enabled"];
218 MainConsole.Instance.OutputFormat("{0}) {1} {2} rev. {3}",
219 k,
220 enabled == true ? "[ ]" : "[X]",
221 plugin["name"], plugin["version"]);
222 }
223 return;
224 }
225
226 // List available plugins on registered repositories
227 private void HandleConsoleListAvailablePlugin(string module, string[] cmd)
228 {
229 Dictionary<string, object> result = new Dictionary<string, object>();
230 PluginManager.ListAvailable(out result);
231
232 var list = result.Keys.ToList();
233 list.Sort();
234 foreach (var k in list)
235 {
236 // name, version, repository
237 Dictionary<string, object> plugin = (Dictionary<string, object>)result[k];
238 MainConsole.Instance.OutputFormat("{0}) {1} rev. {2} {3}",
239 k,
240 plugin["name"],
241 plugin["version"],
242 plugin["repository"]);
243 }
244 return;
245 }
246
247 // List available updates **not ready
248 private void HandleConsoleListUpdates(string module, string[] cmd)
249 {
250 PluginManager.ListUpdates();
251 return;
252 }
253
254 // Update plugin **not ready
255 private void HandleConsoleUpdatePlugin(string module, string[] cmd)
256 {
257 MainConsole.Instance.Output(PluginManager.Update());
258 return;
259 }
260
261 // Register repository
262 private void HandleConsoleAddRepo(string module, string[] cmd)
263 {
264 if ( cmd.Length == 3)
265 {
266 PluginManager.AddRepository(cmd[2]);
267 }
268 return;
269 }
270
271 // Get repository status **not working
272 private void HandleConsoleGetRepo(string module, string[] cmd)
273 {
274 PluginManager.GetRepository();
275 return;
276 }
277
278 // Remove registered repository
279 private void HandleConsoleRemoveRepo(string module, string[] cmd)
280 {
281 if (cmd.Length == 3)
282 PluginManager.RemoveRepository(cmd);
283 return;
284 }
285
286 // Enable repository
287 private void HandleConsoleEnableRepo(string module, string[] cmd)
288 {
289 PluginManager.EnableRepository(cmd);
290 return;
291 }
292
293 // Disable repository
294 private void HandleConsoleDisableRepo(string module, string[] cmd)
295 {
296 PluginManager.DisableRepository(cmd);
297 return;
298 }
299
300 // List repositories
301 private void HandleConsoleListRepos(string module, string[] cmd)
302 {
303 Dictionary<string, object> result = new Dictionary<string, object>();
304 PluginManager.ListRepositories(out result);
305
306 var list = result.Keys.ToList();
307 list.Sort();
308 foreach (var k in list)
309 {
310 Dictionary<string, object> repo = (Dictionary<string, object>)result[k];
311 bool enabled = (bool)repo["enabled"];
312 MainConsole.Instance.OutputFormat("{0}) {1} {2}",
313 k,
314 enabled == true ? "[ ]" : "[X]",
315 repo["name"], repo["url"]);
316 }
317
318 return;
319 }
320
321 // Show description information
322 private void HandleConsoleShowAddinInfo(string module, string[] cmd)
323 {
324 if (cmd.Length >= 3)
325 {
326
327 Dictionary<string, object> result = new Dictionary<string, object>();
328
329 int ndx = Convert.ToInt16(cmd[2]);
330 PluginManager.AddinInfo(ndx, out result);
331
332 MainConsole.Instance.OutputFormat("Name: {0}\nURL: {1}\nFile: {2}\nAuthor: {3}\nCategory: {4}\nDesc: {5}",
333 result["name"],
334 result["url"],
335 result["file_name"],
336 result["author"],
337 result["category"],
338 result["description"]);
339
340 return;
341 }
342 }
343
344 // Disable plugin
345 private void HandleConsoleDisablePlugin(string module, string[] cmd)
346 {
347 PluginManager.DisablePlugin(cmd);
348 return;
349 }
350
351 // Enable plugin
352 private void HandleConsoleEnablePlugin(string module, string[] cmd)
353 {
354 PluginManager.EnablePlugin(cmd);
355 return;
356 }
357 #endregion
358 }
359} \ No newline at end of file
diff --git a/OpenSim/Server/Base/Properties/AssemblyInfo.cs b/OpenSim/Server/Base/Properties/AssemblyInfo.cs
index 4bbe358..8b45564 100644
--- a/OpenSim/Server/Base/Properties/AssemblyInfo.cs
+++ b/OpenSim/Server/Base/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs
index 42c82cf..2e6d279 100644
--- a/OpenSim/Server/Base/ServerUtils.cs
+++ b/OpenSim/Server/Base/ServerUtils.cs
@@ -33,11 +33,163 @@ using System.Xml.Serialization;
33using System.Text; 33using System.Text;
34using System.Collections.Generic; 34using System.Collections.Generic;
35using log4net; 35using log4net;
36using Nini.Config;
36using OpenSim.Framework; 37using OpenSim.Framework;
37using OpenMetaverse; 38using OpenMetaverse;
39using Mono.Addins;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Framework.Servers;
38 42
43
44[assembly:AddinRoot("Robust", "0.1")]
39namespace OpenSim.Server.Base 45namespace OpenSim.Server.Base
40{ 46{
47 [TypeExtensionPoint(Path="/Robust/Connector", Name="RobustConnector")]
48 public interface IRobustConnector
49 {
50 string ConfigName
51 {
52 get;
53 }
54
55 bool Enabled
56 {
57 get;
58 }
59
60 string PluginPath
61 {
62 get;
63 set;
64 }
65
66 uint Configure(IConfigSource config);
67 void Initialize(IHttpServer server);
68 void Unload();
69 }
70
71 public class PluginLoader
72 {
73 static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
74
75 public AddinRegistry Registry
76 {
77 get;
78 private set;
79 }
80
81 public IConfigSource Config
82 {
83 get;
84 private set;
85 }
86
87 public PluginLoader(IConfigSource config, string registryPath)
88 {
89 Config = config;
90
91 Registry = new AddinRegistry(registryPath, ".");
92 suppress_console_output_(true);
93 AddinManager.Initialize(registryPath);
94 suppress_console_output_(false);
95 AddinManager.Registry.Update();
96 CommandManager commandmanager = new CommandManager(Registry);
97 AddinManager.AddExtensionNodeHandler("/Robust/Connector", OnExtensionChanged);
98 }
99
100 private static TextWriter prev_console_;
101 // Temporarily masking the errors reported on start
102 // This is caused by a non-managed dll in the ./bin dir
103 // when the registry is initialized. The dll belongs to
104 // libomv, which has a hard-coded path to "." for pinvoke
105 // to load the openjpeg dll
106 //
107 // Will look for a way to fix, but for now this keeps the
108 // confusion to a minimum. this was copied from our region
109 // plugin loader, we have been doing this in there for a long time.
110 //
111 public void suppress_console_output_(bool save)
112 {
113 if (save)
114 {
115 prev_console_ = System.Console.Out;
116 System.Console.SetOut(new StreamWriter(Stream.Null));
117 }
118 else
119 {
120 if (prev_console_ != null)
121 System.Console.SetOut(prev_console_);
122 }
123 }
124
125 private void OnExtensionChanged(object s, ExtensionNodeEventArgs args)
126 {
127 IRobustConnector connector = (IRobustConnector)args.ExtensionObject;
128 Addin a = Registry.GetAddin(args.ExtensionNode.Addin.Id);
129
130 if(a == null)
131 {
132 Registry.Rebuild(null);
133 a = Registry.GetAddin(args.ExtensionNode.Addin.Id);
134 }
135
136 switch(args.Change)
137 {
138 case ExtensionChange.Add:
139 if (a.AddinFile.Contains(Registry.DefaultAddinsFolder))
140 {
141 m_log.InfoFormat("[SERVER]: Adding {0} from registry", a.Name);
142 connector.PluginPath = System.IO.Path.Combine(Registry.DefaultAddinsFolder,a.Name.Replace(',', '.')); }
143 else
144 {
145 m_log.InfoFormat("[SERVER]: Adding {0} from ./bin", a.Name);
146 connector.PluginPath = a.AddinFile;
147 }
148 LoadPlugin(connector);
149 break;
150 case ExtensionChange.Remove:
151 m_log.InfoFormat("[SERVER]: Removing {0}", a.Name);
152 UnloadPlugin(connector);
153 break;
154 }
155 }
156
157 private void LoadPlugin(IRobustConnector connector)
158 {
159 IHttpServer server = null;
160 uint port = connector.Configure(Config);
161
162 if(connector.Enabled)
163 {
164 server = GetServer(connector, port);
165 connector.Initialize(server);
166 }
167 else
168 {
169 m_log.InfoFormat("[SERVER]: {0} Disabled.", connector.ConfigName);
170 }
171 }
172
173 private void UnloadPlugin(IRobustConnector connector)
174 {
175 m_log.InfoFormat("[Server]: Unloading {0}", connector.ConfigName);
176
177 connector.Unload();
178 }
179
180 private IHttpServer GetServer(IRobustConnector connector, uint port)
181 {
182 IHttpServer server;
183
184 if(port != 0)
185 server = MainServer.GetHttpServer(port);
186 else
187 server = MainServer.Instance;
188
189 return server;
190 }
191 }
192
41 public static class ServerUtils 193 public static class ServerUtils
42 { 194 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 195 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -63,20 +215,30 @@ namespace OpenSim.Server.Base
63 /// <param name="dllName"></param> 215 /// <param name="dllName"></param>
64 /// <param name="args">The arguments which control which constructor is invoked on the plugin</param> 216 /// <param name="args">The arguments which control which constructor is invoked on the plugin</param>
65 /// <returns></returns> 217 /// <returns></returns>
66 public static T LoadPlugin<T>(string dllName, Object[] args) where T:class 218 public static T LoadPlugin<T> (string dllName, Object[] args) where T:class
67 { 219 {
68 // This is good to debug configuration problems 220 // This is good to debug configuration problems
69 //if (dllName == string.Empty) 221 //if (dllName == string.Empty)
70 // Util.PrintCallStack(); 222 // Util.PrintCallStack();
71 223
72 string[] parts = dllName.Split(new char[] {':'});
73
74 dllName = parts[0];
75
76 string className = String.Empty; 224 string className = String.Empty;
77 225
78 if (parts.Length > 1) 226 // The path for a dynamic plugin will contain ":" on Windows
79 className = parts[1]; 227 string[] parts = dllName.Split (new char[] {':'});
228
229 if (parts [0].Length > 1)
230 {
231 dllName = parts [0];
232 if (parts.Length > 1)
233 className = parts[1];
234 }
235 else
236 {
237 // This is Windows - we must replace the ":" in the path
238 dllName = String.Format ("{0}:{1}", parts [0], parts [1]);
239 if (parts.Length > 2)
240 className = parts[2];
241 }
80 242
81 return LoadPlugin<T>(dllName, className, args); 243 return LoadPlugin<T>(dllName, className, args);
82 } 244 }
@@ -118,8 +280,11 @@ namespace OpenSim.Server.Base
118 { 280 {
119 if (!(e is System.MissingMethodException)) 281 if (!(e is System.MissingMethodException))
120 { 282 {
121 m_log.ErrorFormat("Error loading plugin {0} from {1}. Exception: {2}", 283 m_log.ErrorFormat("Error loading plugin {0} from {1}. Exception: {2}, {3}",
122 interfaceName, dllName, e.InnerException == null ? e.Message : e.InnerException.Message); 284 interfaceName,
285 dllName,
286 e.InnerException == null ? e.Message : e.InnerException.Message,
287 e.StackTrace);
123 } 288 }
124 return null; 289 return null;
125 } 290 }
@@ -333,5 +498,42 @@ namespace OpenSim.Server.Base
333 498
334 return ret; 499 return ret;
335 } 500 }
501
502 public static IConfig GetConfig(string configFile, string configName)
503 {
504 IConfig config;
505
506 if (File.Exists(configFile))
507 {
508 IConfigSource configsource = new IniConfigSource(configFile);
509 config = configsource.Configs[configName];
510 }
511 else
512 config = null;
513
514 return config;
515 }
516
517 public static IConfigSource LoadInitialConfig(string url)
518 {
519 IConfigSource source = new XmlConfigSource();
520 m_log.InfoFormat("[CONFIG]: {0} is a http:// URI, fetching ...", url);
521
522 // The ini file path is a http URI
523 // Try to read it
524 try
525 {
526 XmlReader r = XmlReader.Create(url);
527 IConfigSource cs = new XmlConfigSource(r);
528 source.Merge(cs);
529 }
530 catch (Exception e)
531 {
532 m_log.FatalFormat("[CONFIG]: Exception reading config from URI {0}\n" + e.ToString(), url);
533 Environment.Exit(1);
534 }
535
536 return source;
537 }
336 } 538 }
337} 539}
diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index 5b23149..ecd69b0 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -56,6 +56,12 @@ namespace OpenSim.Server.Base
56 // 56 //
57 protected string[] m_Arguments; 57 protected string[] m_Arguments;
58 58
59 public string ConfigDirectory
60 {
61 get;
62 private set;
63 }
64
59 // Run flag 65 // Run flag
60 // 66 //
61 private bool m_Running = true; 67 private bool m_Running = true;
@@ -134,6 +140,8 @@ namespace OpenSim.Server.Base
134 startupConfig = Config.Configs["Startup"]; 140 startupConfig = Config.Configs["Startup"];
135 } 141 }
136 142
143 ConfigDirectory = startupConfig.GetString("ConfigDirectory", ".");
144
137 prompt = startupConfig.GetString("Prompt", prompt); 145 prompt = startupConfig.GetString("Prompt", prompt);
138 146
139 // Allow derived classes to load config before the console is 147 // Allow derived classes to load config before the console is
@@ -242,4 +250,4 @@ namespace OpenSim.Server.Base
242 { 250 {
243 } 251 }
244 } 252 }
245} \ No newline at end of file 253}
diff --git a/OpenSim/Server/Handlers/Base/ServerConnector.cs b/OpenSim/Server/Handlers/Base/ServerConnector.cs
index 71876da..72014db 100644
--- a/OpenSim/Server/Handlers/Base/ServerConnector.cs
+++ b/OpenSim/Server/Handlers/Base/ServerConnector.cs
@@ -39,8 +39,75 @@ namespace OpenSim.Server.Handlers.Base
39 39
40 public class ServiceConnector : IServiceConnector 40 public class ServiceConnector : IServiceConnector
41 { 41 {
42 public virtual string ConfigURL
43 {
44 get { return String.Empty; }
45 }
46
47 public virtual string ConfigName
48 {
49 get;
50 protected set;
51 }
52
53 public virtual string ConfigFile
54 {
55 get;
56 protected set;
57 }
58
59 public virtual IConfigSource Config
60 {
61 get;
62 protected set;
63 }
64
65 public ServiceConnector()
66 {
67 }
68
42 public ServiceConnector(IConfigSource config, IHttpServer server, string configName) 69 public ServiceConnector(IConfigSource config, IHttpServer server, string configName)
43 { 70 {
44 } 71 }
72
73 // We call this from our plugin module to get our configuration
74 public IConfig GetConfig()
75 {
76 IConfig config = null;
77 config = ServerUtils.GetConfig(ConfigFile, ConfigName);
78
79 // Our file is not here? We can get one to bootstrap our plugin module
80 if ( config == null )
81 {
82 IConfigSource remotesource = GetConfigSource();
83
84 if (remotesource != null)
85 {
86 IniConfigSource initialconfig = new IniConfigSource();
87 initialconfig.Merge (remotesource);
88 initialconfig.Save(ConfigFile);
89 }
90
91 config = remotesource.Configs[ConfigName];
92 }
93
94 return config;
95 }
96
97 // We get our remote initial configuration for bootstrapping in case
98 // we have no configuration in our main file or in an existing
99 // modular config file. This is the last resort to bootstrap the
100 // configuration, likely a new plugin loading for the first time.
101 private IConfigSource GetConfigSource()
102 {
103 IConfigSource source = null;
104
105 source = ServerUtils.LoadInitialConfig(ConfigURL);
106
107 if (source == null)
108 System.Console.WriteLine(String.Format ("Config Url: {0} Not found!", ConfigURL));
109
110 return source;
111 }
45 } 112 }
46} 113}
diff --git a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
index 53e9737..d72d36a 100644
--- a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Server/Properties/AssemblyInfo.cs b/OpenSim/Server/Properties/AssemblyInfo.cs
index ebc10fb..ee45e10 100644
--- a/OpenSim/Server/Properties/AssemblyInfo.cs
+++ b/OpenSim/Server/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs
index 45c13fb..8be69a9 100644
--- a/OpenSim/Server/ServerMain.cs
+++ b/OpenSim/Server/ServerMain.cs
@@ -34,6 +34,7 @@ using OpenSim.Framework.Servers;
34using OpenSim.Framework.Servers.HttpServer; 34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Server.Base; 35using OpenSim.Server.Base;
36using OpenSim.Server.Handlers.Base; 36using OpenSim.Server.Handlers.Base;
37using Mono.Addins;
37 38
38namespace OpenSim.Server 39namespace OpenSim.Server
39{ 40{
@@ -48,9 +49,13 @@ namespace OpenSim.Server
48 protected static List<IServiceConnector> m_ServiceConnectors = 49 protected static List<IServiceConnector> m_ServiceConnectors =
49 new List<IServiceConnector>(); 50 new List<IServiceConnector>();
50 51
52 protected static PluginLoader loader;
53
51 public static int Main(string[] args) 54 public static int Main(string[] args)
52 { 55 {
53 m_Server = new HttpServerBase("R.O.B.U.S.T.", args); 56 m_Server = new HttpServerBase("R.O.B.U.S.T.", args);
57
58 string registryLocation;
54 59
55 IConfig serverConfig = m_Server.Config.Configs["Startup"]; 60 IConfig serverConfig = m_Server.Config.Configs["Startup"];
56 if (serverConfig == null) 61 if (serverConfig == null)
@@ -60,6 +65,8 @@ namespace OpenSim.Server
60 } 65 }
61 66
62 string connList = serverConfig.GetString("ServiceConnectors", String.Empty); 67 string connList = serverConfig.GetString("ServiceConnectors", String.Empty);
68
69 registryLocation = serverConfig.GetString("RegistryLocation",".");
63 70
64 IConfig servicesConfig = m_Server.Config.Configs["ServiceList"]; 71 IConfig servicesConfig = m_Server.Config.Configs["ServiceList"];
65 if (servicesConfig != null) 72 if (servicesConfig != null)
@@ -141,6 +148,9 @@ namespace OpenSim.Server
141 m_log.InfoFormat("[SERVER]: Failed to load {0}", conn); 148 m_log.InfoFormat("[SERVER]: Failed to load {0}", conn);
142 } 149 }
143 } 150 }
151
152 loader = new PluginLoader(m_Server.Config, registryLocation);
153
144 int res = m_Server.Run(); 154 int res = m_Server.Run();
145 155
146 Environment.Exit(res); 156 Environment.Exit(res);
diff --git a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
index 1509400..b57052c 100644
--- a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
index 0eb2ba7..99c46ec 100644
--- a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
index 6d6b11e..33e48d3 100644
--- a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
index 0944149..8b0214a 100644
--- a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/Base/Properties/AssemblyInfo.cs b/OpenSim/Services/Base/Properties/AssemblyInfo.cs
index 306b699..2825a88 100644
--- a/OpenSim/Services/Base/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Base/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
index bfb681b..73fc72c 100644
--- a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index 508baf7..ef2494a 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -315,7 +315,7 @@ namespace OpenSim.Services.Connectors.Simulation
315 315
316 try 316 try
317 { 317 {
318 OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000, false); 318 OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 30000, false);
319 bool success = result["success"].AsBoolean(); 319 bool success = result["success"].AsBoolean();
320 if (result.ContainsKey("_Result")) 320 if (result.ContainsKey("_Result"))
321 { 321 {
diff --git a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
index 58c7283..fdd4b69 100644
--- a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
index dddb091..cb624f0 100644
--- a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index ee3b858..daebf8b 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -185,15 +185,15 @@ namespace OpenSim.Services.GridService
185 185
186 if (!m_AllowDuplicateNames) 186 if (!m_AllowDuplicateNames)
187 { 187 {
188 List<RegionData> dupe = m_Database.Get(regionInfos.RegionName, scopeID); 188 List<RegionData> dupe = m_Database.Get(Util.EscapeForLike(regionInfos.RegionName), scopeID);
189 if (dupe != null && dupe.Count > 0) 189 if (dupe != null && dupe.Count > 0)
190 { 190 {
191 foreach (RegionData d in dupe) 191 foreach (RegionData d in dupe)
192 { 192 {
193 if (d.RegionID != regionInfos.RegionID) 193 if (d.RegionID != regionInfos.RegionID)
194 { 194 {
195 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register duplicate name with ID {1}.", 195 m_log.WarnFormat("[GRID SERVICE]: Region tried to register using a duplicate name. New region: {0} ({1}), existing region: {2} ({3}).",
196 regionInfos.RegionName, regionInfos.RegionID); 196 regionInfos.RegionName, regionInfos.RegionID, d.RegionName, d.RegionID);
197 return "Duplicate region name"; 197 return "Duplicate region name";
198 } 198 }
199 } 199 }
@@ -359,7 +359,7 @@ namespace OpenSim.Services.GridService
359 359
360 public GridRegion GetRegionByName(UUID scopeID, string name) 360 public GridRegion GetRegionByName(UUID scopeID, string name)
361 { 361 {
362 List<RegionData> rdatas = m_Database.Get(name, scopeID); 362 List<RegionData> rdatas = m_Database.Get(Util.EscapeForLike(name), scopeID);
363 if ((rdatas != null) && (rdatas.Count > 0)) 363 if ((rdatas != null) && (rdatas.Count > 0))
364 return RegionData2RegionInfo(rdatas[0]); // get the first 364 return RegionData2RegionInfo(rdatas[0]); // get the first
365 365
@@ -377,7 +377,7 @@ namespace OpenSim.Services.GridService
377 { 377 {
378// m_log.DebugFormat("[GRID SERVICE]: GetRegionsByName {0}", name); 378// m_log.DebugFormat("[GRID SERVICE]: GetRegionsByName {0}", name);
379 379
380 List<RegionData> rdatas = m_Database.Get(name + "%", scopeID); 380 List<RegionData> rdatas = m_Database.Get(Util.EscapeForLike(name) + "%", scopeID);
381 381
382 int count = 0; 382 int count = 0;
383 List<GridRegion> rinfos = new List<GridRegion>(); 383 List<GridRegion> rinfos = new List<GridRegion>();
@@ -586,7 +586,7 @@ namespace OpenSim.Services.GridService
586 586
587 string regionName = cmd[3]; 587 string regionName = cmd[3];
588 588
589 List<RegionData> regions = m_Database.Get(regionName, UUID.Zero); 589 List<RegionData> regions = m_Database.Get(Util.EscapeForLike(regionName), UUID.Zero);
590 if (regions == null || regions.Count < 1) 590 if (regions == null || regions.Count < 1)
591 { 591 {
592 MainConsole.Instance.Output("No region with name {0} found", regionName); 592 MainConsole.Instance.Output("No region with name {0} found", regionName);
@@ -716,7 +716,7 @@ namespace OpenSim.Services.GridService
716 return; 716 return;
717 } 717 }
718 718
719 List<RegionData> regions = m_Database.Get(cmd[3], UUID.Zero); 719 List<RegionData> regions = m_Database.Get(Util.EscapeForLike(cmd[3]), UUID.Zero);
720 if (regions == null || regions.Count < 1) 720 if (regions == null || regions.Count < 1)
721 { 721 {
722 MainConsole.Instance.Output("Region not found"); 722 MainConsole.Instance.Output("Region not found");
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
index 743d089..073197f 100644
--- a/OpenSim/Services/GridService/HypergridLinker.cs
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -387,7 +387,7 @@ namespace OpenSim.Services.GridService
387 m_log.DebugFormat("[HYPERGRID LINKER]: Request to unlink {0}", mapName); 387 m_log.DebugFormat("[HYPERGRID LINKER]: Request to unlink {0}", mapName);
388 GridRegion regInfo = null; 388 GridRegion regInfo = null;
389 389
390 List<RegionData> regions = m_Database.Get(mapName, m_ScopeID); 390 List<RegionData> regions = m_Database.Get(Util.EscapeForLike(mapName), m_ScopeID);
391 if (regions != null && regions.Count > 0) 391 if (regions != null && regions.Count > 0)
392 { 392 {
393 OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]); 393 OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]);
diff --git a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
index 5c0c8f4..09084d3 100644
--- a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs
index 0c9cfd3..e8d7cca 100644
--- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs
+++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs
@@ -61,13 +61,13 @@ namespace OpenSim.Services.HypergridService
61 protected static IGridService m_GridService; 61 protected static IGridService m_GridService;
62 protected static IPresenceService m_PresenceService; 62 protected static IPresenceService m_PresenceService;
63 protected static IUserAgentService m_UserAgentService; 63 protected static IUserAgentService m_UserAgentService;
64 protected static IOfflineIMService m_OfflineIMService;
64 65
65 protected static IInstantMessageSimConnector m_IMSimConnector; 66 protected static IInstantMessageSimConnector m_IMSimConnector;
66 67
67 protected static Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>(); 68 protected static Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>();
68 private static ExpiringCache<UUID, GridRegion> m_RegionCache; 69 private static ExpiringCache<UUID, GridRegion> m_RegionCache;
69 70
70 private static string m_RestURL;
71 private static bool m_ForwardOfflineGroupMessages; 71 private static bool m_ForwardOfflineGroupMessages;
72 private static bool m_InGatekeeper; 72 private static bool m_InGatekeeper;
73 73
@@ -111,9 +111,14 @@ namespace OpenSim.Services.HypergridService
111 return; 111 return;
112 } 112 }
113 113
114 m_RestURL = cnf.GetString("OfflineMessageURL", string.Empty);
115 m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", false); 114 m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", false);
116 115
116 if (m_InGatekeeper)
117 {
118 string offlineIMService = cnf.GetString("OfflineIMService", string.Empty);
119 if (offlineIMService != string.Empty)
120 m_OfflineIMService = ServerUtils.LoadPlugin<IOfflineIMService>(offlineIMService, args);
121 }
117 } 122 }
118 } 123 }
119 124
@@ -329,18 +334,28 @@ namespace OpenSim.Services.HypergridService
329 334
330 private bool UndeliveredMessage(GridInstantMessage im) 335 private bool UndeliveredMessage(GridInstantMessage im)
331 { 336 {
332 if (m_RestURL != string.Empty && (im.offline != 0) 337 if (m_OfflineIMService == null)
333 && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) 338 return false;
334 {
335// m_log.DebugFormat("[HG IM SERVICE]: Message saved");
336 339
337 return SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>( 340 if (im.dialog != (byte)InstantMessageDialog.MessageFromObject &&
338 "POST", m_RestURL + "/SaveMessage/", im); 341 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
339 } 342 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
340 else 343 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
344 im.dialog != (byte)InstantMessageDialog.InventoryOffered)
341 { 345 {
342 return false; 346 return false;
343 } 347 }
348
349 if (!m_ForwardOfflineGroupMessages)
350 {
351 if (im.dialog == (byte)InstantMessageDialog.GroupNotice ||
352 im.dialog == (byte)InstantMessageDialog.GroupInvitation)
353 return false;
354 }
355
356// m_log.DebugFormat("[HG IM SERVICE]: Message saved");
357 string reason = string.Empty;
358 return m_OfflineIMService.StoreMessage(im, out reason);
344 } 359 }
345 } 360 }
346} \ No newline at end of file 361} \ No newline at end of file
diff --git a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
index 49f2176..fe1889d 100644
--- a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/Interfaces/IOfflineIMService.cs b/OpenSim/Services/Interfaces/IOfflineIMService.cs
new file mode 100644
index 0000000..2848967
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IOfflineIMService.cs
@@ -0,0 +1,115 @@
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 */
27using System;
28using System.Collections.Generic;
29
30using OpenSim.Framework;
31using OpenMetaverse;
32
33namespace OpenSim.Services.Interfaces
34{
35 public interface IOfflineIMService
36 {
37 List<GridInstantMessage> GetMessages(UUID principalID);
38 bool StoreMessage(GridInstantMessage im, out string reason);
39 }
40
41 public class OfflineIMDataUtils
42 {
43 public static GridInstantMessage GridInstantMessage(Dictionary<string, object> dict)
44 {
45 GridInstantMessage im = new GridInstantMessage();
46
47 if (dict.ContainsKey("BinaryBucket") && dict["BinaryBucket"] != null)
48 im.binaryBucket = OpenMetaverse.Utils.HexStringToBytes(dict["BinaryBucket"].ToString(), true);
49
50 if (dict.ContainsKey("Dialog") && dict["Dialog"] != null)
51 im.dialog = byte.Parse(dict["Dialog"].ToString());
52
53 if (dict.ContainsKey("FromAgentID") && dict["FromAgentID"] != null)
54 im.fromAgentID = new Guid(dict["FromAgentID"].ToString());
55
56 if (dict.ContainsKey("FromAgentName") && dict["FromAgentName"] != null)
57 im.fromAgentName = dict["FromAgentName"].ToString();
58 else
59 im.fromAgentName = string.Empty;
60
61 if (dict.ContainsKey("FromGroup") && dict["FromGroup"] != null)
62 im.fromGroup = bool.Parse(dict["FromGroup"].ToString());
63
64 if (dict.ContainsKey("SessionID") && dict["SessionID"] != null)
65 im.imSessionID = new Guid(dict["SessionID"].ToString());
66
67 if (dict.ContainsKey("Message") && dict["Message"] != null)
68 im.message = dict["Message"].ToString();
69 else
70 im.message = string.Empty;
71
72 if (dict.ContainsKey("Offline") && dict["Offline"] != null)
73 im.offline = byte.Parse(dict["Offline"].ToString());
74
75 if (dict.ContainsKey("EstateID") && dict["EstateID"] != null)
76 im.ParentEstateID = UInt32.Parse(dict["EstateID"].ToString());
77
78 if (dict.ContainsKey("Position") && dict["Position"] != null)
79 im.Position = Vector3.Parse(dict["Position"].ToString());
80
81 if (dict.ContainsKey("RegionID") && dict["RegionID"] != null)
82 im.RegionID = new Guid(dict["RegionID"].ToString());
83
84 if (dict.ContainsKey("Timestamp") && dict["Timestamp"] != null)
85 im.timestamp = UInt32.Parse(dict["Timestamp"].ToString());
86
87 if (dict.ContainsKey("ToAgentID") && dict["ToAgentID"] != null)
88 im.toAgentID = new Guid(dict["ToAgentID"].ToString());
89
90 return im;
91 }
92
93 public static Dictionary<string, object> GridInstantMessage(GridInstantMessage im)
94 {
95 Dictionary<string, object> dict = new Dictionary<string, object>();
96
97 dict["BinaryBucket"] = OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, im.binaryBucket.Length, null);
98 dict["Dialog"] = im.dialog.ToString();
99 dict["FromAgentID"] = im.fromAgentID.ToString();
100 dict["FromAgentName"] = im.fromAgentName == null ? string.Empty : im.fromAgentName;
101 dict["FromGroup"] = im.fromGroup.ToString();
102 dict["SessionID"] = im.imSessionID.ToString();
103 dict["Message"] = im.message == null ? string.Empty : im.message;
104 dict["Offline"] = im.offline.ToString();
105 dict["EstateID"] = im.ParentEstateID.ToString();
106 dict["Position"] = im.Position.ToString();
107 dict["RegionID"] = im.RegionID.ToString();
108 dict["Timestamp"] = im.timestamp.ToString();
109 dict["ToAgentID"] = im.toAgentID.ToString();
110
111 return dict;
112 }
113
114 }
115}
diff --git a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
index 4723553..669e0b8 100644
--- a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
index 41ad9f8..0870065 100644
--- a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index 00faa44..7bad4b0 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -219,9 +219,15 @@ namespace OpenSim.Services.InventoryService
219 219
220 XInventoryFolder root = null; 220 XInventoryFolder root = null;
221 foreach (XInventoryFolder folder in folders) 221 foreach (XInventoryFolder folder in folders)
222 {
222 if (folder.folderName == "My Inventory") 223 if (folder.folderName == "My Inventory")
224 {
223 root = folder; 225 root = folder;
224 if (folders == null) // oops 226 break;
227 }
228 }
229
230 if (root == null) // oops
225 root = folders[0]; 231 root = folders[0];
226 232
227 return ConvertToOpenSim(root); 233 return ConvertToOpenSim(root);
@@ -249,6 +255,9 @@ namespace OpenSim.Services.InventoryService
249 { 255 {
250// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); 256// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
251 257
258 if (type == AssetType.RootFolder)
259 return rootFolder;
260
252 XInventoryFolder[] folders = m_Database.GetFolders( 261 XInventoryFolder[] folders = m_Database.GetFolders(
253 new string[] { "agentID", "parentFolderID", "type"}, 262 new string[] { "agentID", "parentFolderID", "type"},
254 new string[] { rootFolder.Owner.ToString(), rootFolder.ID.ToString(), ((int)type).ToString() }); 263 new string[] { rootFolder.Owner.ToString(), rootFolder.ID.ToString(), ((int)type).ToString() });
diff --git a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
index 62c6e0f..3ac8af7 100644
--- a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
index 23eb664..69adf73 100644
--- a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
index 8c03dd7..040bbe0 100644
--- a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
index 24e1d16..576ccce 100644
--- a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs
index 95c2935..a4f1bba 100644
--- a/OpenSim/Services/UserAccountService/UserAccountService.cs
+++ b/OpenSim/Services/UserAccountService/UserAccountService.cs
@@ -564,7 +564,7 @@ namespace OpenSim.Services.UserAccountService
564 return account; 564 return account;
565 } 565 }
566 566
567 private void CreateDefaultAppearanceEntries(UUID principalID) 567 protected void CreateDefaultAppearanceEntries(UUID principalID)
568 { 568 {
569 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default appearance items for {0}", principalID); 569 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default appearance items for {0}", principalID);
570 570
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
index ea3e348..dc20f13 100644
--- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
@@ -139,7 +139,7 @@ namespace OpenSim.Tests.Common
139 SceneCommunicationService scs = new SceneCommunicationService(); 139 SceneCommunicationService scs = new SceneCommunicationService();
140 140
141 TestScene testScene = new TestScene( 141 TestScene testScene = new TestScene(
142 regInfo, m_acm, scs, m_simDataService, m_estateDataService, false, configSource, null); 142 regInfo, m_acm, scs, m_simDataService, m_estateDataService, configSource, null);
143 143
144 INonSharedRegionModule godsModule = new GodsModule(); 144 INonSharedRegionModule godsModule = new GodsModule();
145 godsModule.Initialise(new IniConfigSource()); 145 godsModule.Initialise(new IniConfigSource());
diff --git a/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs b/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs
index 6fb9df1..3035cea 100644
--- a/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs
+++ b/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs
@@ -26,12 +26,15 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
31using log4net; 32using log4net;
32using Mono.Addins; 33using Mono.Addins;
33using Nini.Config; 34using Nini.Config;
34using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Data;
37using OpenSim.Data.Null;
35using OpenSim.Framework; 38using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
@@ -44,6 +47,8 @@ namespace OpenSim.Tests.Common.Mock
44 { 47 {
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
50 IXGroupData m_data = new NullXGroupData(null, null);
51
47 public string Name 52 public string Name
48 { 53 {
49 get { return "MockGroupsServicesConnector"; } 54 get { return "MockGroupsServicesConnector"; }
@@ -84,7 +89,33 @@ namespace OpenSim.Tests.Common.Mock
84 int membershipFee, bool openEnrollment, bool allowPublish, 89 int membershipFee, bool openEnrollment, bool allowPublish,
85 bool maturePublish, UUID founderID) 90 bool maturePublish, UUID founderID)
86 { 91 {
87 return UUID.Zero; 92 XGroup group = new XGroup()
93 {
94 groupID = UUID.Random(),
95 ownerRoleID = UUID.Random(),
96 name = name,
97 charter = charter,
98 showInList = showInList,
99 insigniaID = insigniaID,
100 membershipFee = membershipFee,
101 openEnrollment = openEnrollment,
102 allowPublish = allowPublish,
103 maturePublish = maturePublish,
104 founderID = founderID,
105 everyonePowers = (ulong)XmlRpcGroupsServicesConnectorModule.DefaultEveryonePowers,
106 ownersPowers = (ulong)XmlRpcGroupsServicesConnectorModule.DefaultOwnerPowers
107 };
108
109 if (m_data.StoreGroup(group))
110 {
111 m_log.DebugFormat("[MOCK GROUPS SERVICES CONNECTOR]: Created group {0} {1}", group.name, group.groupID);
112 return group.groupID;
113 }
114 else
115 {
116 m_log.ErrorFormat("[MOCK GROUPS SERVICES CONNECTOR]: Failed to create group {0}", name);
117 return UUID.Zero;
118 }
88 } 119 }
89 120
90 public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, 121 public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList,
@@ -107,9 +138,49 @@ namespace OpenSim.Tests.Common.Mock
107 { 138 {
108 } 139 }
109 140
110 public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID GroupID, string GroupName) 141 public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName)
111 { 142 {
112 return null; 143 m_log.DebugFormat(
144 "[MOCK GROUPS SERVICES CONNECTOR]: Processing GetGroupRecord() for groupID {0}, name {1}",
145 groupID, groupName);
146
147 XGroup[] groups;
148 string field, val;
149
150 if (groupID != UUID.Zero)
151 {
152 field = "groupID";
153 val = groupID.ToString();
154 }
155 else
156 {
157 field = "name";
158 val = groupName;
159 }
160
161 groups = m_data.GetGroups(field, val);
162
163 if (groups.Length == 0)
164 return null;
165
166 XGroup xg = groups[0];
167
168 GroupRecord gr = new GroupRecord()
169 {
170 GroupID = xg.groupID,
171 GroupName = xg.name,
172 AllowPublish = xg.allowPublish,
173 MaturePublish = xg.maturePublish,
174 Charter = xg.charter,
175 FounderID = xg.founderID,
176 // FIXME: group picture storage location unknown
177 MembershipFee = xg.membershipFee,
178 OpenEnrollment = xg.openEnrollment,
179 OwnerRoleID = xg.ownerRoleID,
180 ShowInList = xg.showInList
181 };
182
183 return gr;
113 } 184 }
114 185
115 public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID) 186 public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID)
diff --git a/OpenSim/Tests/Common/Mock/MockScriptEngine.cs b/OpenSim/Tests/Common/Mock/MockScriptEngine.cs
new file mode 100644
index 0000000..78bab5b
--- /dev/null
+++ b/OpenSim/Tests/Common/Mock/MockScriptEngine.cs
@@ -0,0 +1,214 @@
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.Reflection;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared;
38
39namespace OpenSim.Tests.Common
40{
41 public class MockScriptEngine : INonSharedRegionModule, IScriptModule, IScriptEngine
42 {
43 private Scene m_scene;
44
45 public void Initialise(IConfigSource source)
46 {
47 }
48
49 public void Close()
50 {
51 }
52
53 public void AddRegion(Scene scene)
54 {
55 m_scene = scene;
56
57 m_scene.StackModuleInterface<IScriptModule>(this);
58 }
59
60 public void RemoveRegion(Scene scene)
61 {
62 }
63
64 public void RegionLoaded(Scene scene)
65 {
66 }
67
68 public string Name { get { return "Mock Script Engine"; } }
69 public string ScriptEngineName { get { return Name; } }
70
71 public Type ReplaceableInterface { get { return null; } }
72
73 public event ScriptRemoved OnScriptRemoved;
74 public event ObjectRemoved OnObjectRemoved;
75
76 public string GetXMLState (UUID itemID)
77 {
78 throw new System.NotImplementedException ();
79 }
80
81 public bool SetXMLState(UUID itemID, string xml)
82 {
83 throw new System.NotImplementedException ();
84 }
85
86 public bool PostScriptEvent(UUID itemID, string name, object[] args)
87 {
88 return false;
89 }
90
91 public bool PostObjectEvent(UUID itemID, string name, object[] args)
92 {
93 throw new System.NotImplementedException ();
94 }
95
96 public void SuspendScript(UUID itemID)
97 {
98 throw new System.NotImplementedException ();
99 }
100
101 public void ResumeScript(UUID itemID)
102 {
103 throw new System.NotImplementedException ();
104 }
105
106 public ArrayList GetScriptErrors(UUID itemID)
107 {
108 throw new System.NotImplementedException ();
109 }
110
111 public bool HasScript(UUID itemID, out bool running)
112 {
113 throw new System.NotImplementedException ();
114 }
115
116 public bool GetScriptState(UUID itemID)
117 {
118 throw new System.NotImplementedException ();
119 }
120
121 public void SaveAllState()
122 {
123 throw new System.NotImplementedException ();
124 }
125
126 public void StartProcessing()
127 {
128 throw new System.NotImplementedException ();
129 }
130
131 public float GetScriptExecutionTime(List<UUID> itemIDs)
132 {
133 throw new System.NotImplementedException ();
134 }
135
136 public Dictionary<uint, float> GetObjectScriptsExecutionTimes()
137 {
138 throw new System.NotImplementedException ();
139 }
140
141 public IScriptWorkItem QueueEventHandler(object parms)
142 {
143 throw new System.NotImplementedException ();
144 }
145
146 public bool PostScriptEvent(UUID itemID,EventParams parms)
147 {
148 throw new System.NotImplementedException ();
149 }
150
151 public bool PostObjectEvent (uint localID, EventParams parms)
152 {
153 throw new System.NotImplementedException ();
154 }
155
156 public DetectParams GetDetectParams(UUID item, int number)
157 {
158 throw new System.NotImplementedException ();
159 }
160
161 public void SetMinEventDelay(UUID itemID, double delay)
162 {
163 throw new System.NotImplementedException ();
164 }
165
166 public int GetStartParameter(UUID itemID)
167 {
168 throw new System.NotImplementedException ();
169 }
170
171 public void SetScriptState(UUID itemID, bool state)
172 {
173 throw new System.NotImplementedException ();
174 }
175
176 public void SetState(UUID itemID, string newState)
177 {
178 throw new System.NotImplementedException ();
179 }
180
181 public void ApiResetScript(UUID itemID)
182 {
183 throw new System.NotImplementedException ();
184 }
185
186 public void ResetScript (UUID itemID)
187 {
188 throw new System.NotImplementedException ();
189 }
190
191 public IScriptApi GetApi(UUID itemID, string name)
192 {
193 throw new System.NotImplementedException ();
194 }
195
196 public Scene World { get { return m_scene; } }
197
198 public IScriptModule ScriptModule { get { throw new System.NotImplementedException(); } }
199
200 public IConfig Config { get { throw new System.NotImplementedException (); } }
201
202 public IConfigSource ConfigSource { get { throw new System.NotImplementedException (); } }
203
204 public string ScriptEnginePath { get { throw new System.NotImplementedException (); }}
205
206 public string ScriptClassName { get { throw new System.NotImplementedException (); } }
207
208 public string ScriptBaseClassName { get { throw new System.NotImplementedException (); } }
209
210 public string[] ScriptReferencedAssemblies { get { throw new System.NotImplementedException (); } }
211
212 public ParameterInfo[] ScriptBaseClassParameters { get { throw new System.NotImplementedException (); } }
213 }
214} \ No newline at end of file
diff --git a/OpenSim/Tests/Common/Mock/TestScene.cs b/OpenSim/Tests/Common/Mock/TestScene.cs
index d4b5648..a7e0dfb 100644
--- a/OpenSim/Tests/Common/Mock/TestScene.cs
+++ b/OpenSim/Tests/Common/Mock/TestScene.cs
@@ -41,10 +41,9 @@ namespace OpenSim.Tests.Common.Mock
41 public TestScene( 41 public TestScene(
42 RegionInfo regInfo, AgentCircuitManager authen, 42 RegionInfo regInfo, AgentCircuitManager authen,
43 SceneCommunicationService sceneGridService, ISimulationDataService simDataService, IEstateDataService estateDataService, 43 SceneCommunicationService sceneGridService, ISimulationDataService simDataService, IEstateDataService estateDataService,
44 bool dumpAssetsToFile,
45 IConfigSource config, string simulatorVersion) 44 IConfigSource config, string simulatorVersion)
46 : base(regInfo, authen, sceneGridService, simDataService, estateDataService, 45 : base(regInfo, authen, sceneGridService, simDataService, estateDataService,
47 dumpAssetsToFile, config, simulatorVersion) 46 config, simulatorVersion)
48 { 47 {
49 } 48 }
50 49
diff --git a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
index f9bf768..ccbdf81 100644
--- a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
@@ -33,10 +33,11 @@ using log4net;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Data; 35using OpenSim.Data;
36using OpenSim.Data.Null;
36 37
37namespace OpenSim.Tests.Common.Mock 38namespace OpenSim.Tests.Common.Mock
38{ 39{
39 public class TestXInventoryDataPlugin : IXInventoryData 40 public class TestXInventoryDataPlugin : NullGenericDataHandler, IXInventoryData
40 { 41 {
41 private Dictionary<UUID, XInventoryFolder> m_allFolders = new Dictionary<UUID, XInventoryFolder>(); 42 private Dictionary<UUID, XInventoryFolder> m_allFolders = new Dictionary<UUID, XInventoryFolder>();
42 private Dictionary<UUID, XInventoryItem> m_allItems = new Dictionary<UUID, XInventoryItem>(); 43 private Dictionary<UUID, XInventoryItem> m_allItems = new Dictionary<UUID, XInventoryItem>();
@@ -58,28 +59,6 @@ namespace OpenSim.Tests.Common.Mock
58 return origFolders.Select(f => f.Clone()).ToArray(); 59 return origFolders.Select(f => f.Clone()).ToArray();
59 } 60 }
60 61
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) 62 public bool StoreFolder(XInventoryFolder folder)
84 { 63 {
85 m_allFolders[folder.folderID] = folder.Clone(); 64 m_allFolders[folder.folderID] = folder.Clone();
diff --git a/OpenSim/Tests/ConfigurationLoaderTest.cs b/OpenSim/Tests/ConfigurationLoaderTest.cs
index 067264d..e5186ae 100644
--- a/OpenSim/Tests/ConfigurationLoaderTest.cs
+++ b/OpenSim/Tests/ConfigurationLoaderTest.cs
@@ -29,11 +29,12 @@ using System.IO;
29using Nini.Config; 29using Nini.Config;
30using NUnit.Framework; 30using NUnit.Framework;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Tests.Common;
32 33
33namespace OpenSim.Tests 34namespace OpenSim.Tests
34{ 35{
35 [TestFixture] 36 [TestFixture]
36 public class ConfigurationLoaderTests 37 public class ConfigurationLoaderTests : OpenSimTestCase
37 { 38 {
38 private const string m_testSubdirectory = "test"; 39 private const string m_testSubdirectory = "test";
39 private string m_basePath; 40 private string m_basePath;
diff --git a/OpenSim/Tests/Performance/NPCPerformanceTests.cs b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
index afda574..fde1b91 100644
--- a/OpenSim/Tests/Performance/NPCPerformanceTests.cs
+++ b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
@@ -58,7 +58,7 @@ namespace OpenSim.Tests.Performance
58 /// earlier tests. 58 /// earlier tests.
59 /// </remarks> 59 /// </remarks>
60 [TestFixture] 60 [TestFixture]
61 public class NPCPerformanceTests 61 public class NPCPerformanceTests : OpenSimTestCase
62 { 62 {
63 private TestScene scene; 63 private TestScene scene;
64 private AvatarFactoryModule afm; 64 private AvatarFactoryModule afm;
diff --git a/OpenSim/Tests/Performance/ObjectPerformanceTests.cs b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
index 2264d86..656a971 100644
--- a/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
+++ b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Tests.Performance
47 /// earlier tests. 47 /// earlier tests.
48 /// </remarks> 48 /// </remarks>
49 [TestFixture] 49 [TestFixture]
50 public class ObjectPerformanceTests 50 public class ObjectPerformanceTests : OpenSimTestCase
51 { 51 {
52 [TearDown] 52 [TearDown]
53 public void TearDown() 53 public void TearDown()
diff --git a/OpenSim/Tests/Performance/ScriptPerformanceTests.cs b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
index d708abd..4064edc 100644
--- a/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
+++ b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Tests.Performance
53 /// earlier tests. 53 /// earlier tests.
54 /// </remarks> 54 /// </remarks>
55 [TestFixture] 55 [TestFixture]
56 public class ScriptPerformanceTests 56 public class ScriptPerformanceTests : OpenSimTestCase
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/Tools/Compiler/Properties/AssemblyInfo.cs b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
index e1a1fda..b98e2d2 100644
--- a/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
index 62a2f2d..89aafa3 100644
--- a/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
index 20598f1..c4d278a 100644
--- a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TESTING.txt b/TESTING.txt
index 08a0698..e7ab088 100644
--- a/TESTING.txt
+++ b/TESTING.txt
@@ -1,4 +1,4 @@
1=== The Quick Guide to OpenSim Unit Testing === 1= The Quick Guide to OpenSim Unit Testing =
2 2
3== Running Tests == 3== Running Tests ==
4 4
@@ -27,7 +27,7 @@ must list it in both ".nant/local.include"
27for it to be accessible to Linux users and to the continuous 27for it to be accessible to Linux users and to the continuous
28integration system. 28integration system.
29 29
30==TESTING ON WINDOWS== 30== TESTING ON WINDOWS ==
31 31
32To use nunit testing on opensim code, you have a variety of methods. The 32To use nunit testing on opensim code, you have a variety of methods. The
33easiast methods involve using IDE capabilities to test code. Using 33easiast methods involve using IDE capabilities to test code. Using
@@ -58,14 +58,14 @@ Nunit console allows you to execute the nunit tests of assemblies via console.
58Its output will show test failures and successes and a summary of what 58Its output will show test failures and successes and a summary of what
59happened. This is very useful for a quick overview and/or automated testing. 59happened. This is very useful for a quick overview and/or automated testing.
60 60
61Windows 61=== Windows ===
62Windows version of nunit-console is by default .Net 2.0 if you downloaded the 62Windows version of nunit-console is by default .Net 2.0 if you downloaded the
63.Net 2.0 version of Nunit. Be sure to setup your PATH environment variable. 63.Net 2.0 version of Nunit. Be sure to setup your PATH environment variable.
64 64
65Linux & OSX 65=== Linux & OSX ===
66On these operating systems you will have to use the command "nunit-console2" 66On these operating systems you will have to use the command "nunit-console2"
67 67
68Example 68=== Example ===
69 69
70nunit-console2 OpenSim.Framework.Tests.dll (on linux) 70nunit-console2 OpenSim.Framework.Tests.dll (on linux)
71nunit-console OpenSim.Framework.Tests.dll (on windows) 71nunit-console OpenSim.Framework.Tests.dll (on windows)
diff --git a/ThirdParty/SmartThreadPool/AssemblyInfo.cs b/ThirdParty/SmartThreadPool/AssemblyInfo.cs
index af9baff..e2465b0 100644
--- a/ThirdParty/SmartThreadPool/AssemblyInfo.cs
+++ b/ThirdParty/SmartThreadPool/AssemblyInfo.cs
@@ -29,7 +29,7 @@ using System.Runtime.InteropServices;
29// You can specify all the values or you can default the Revision and Build Numbers 29// You can specify all the values or you can default the Revision and Build Numbers
30// by using the '*' as shown below: 30// by using the '*' as shown below:
31 31
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33 33
34// 34//
35// In order to sign your assembly you must specify a key to use. Refer to the 35// In order to sign your assembly you must specify a key to use. Refer to the
diff --git a/ThirdParty/SmartThreadPool/STPStartInfo.cs b/ThirdParty/SmartThreadPool/STPStartInfo.cs
index d181563..fa9ceb4 100644
--- a/ThirdParty/SmartThreadPool/STPStartInfo.cs
+++ b/ThirdParty/SmartThreadPool/STPStartInfo.cs
@@ -33,6 +33,11 @@ namespace Amib.Threading
33 private ThreadPriority _threadPriority; 33 private ThreadPriority _threadPriority;
34 34
35 /// <summary> 35 /// <summary>
36 /// The thread pool name. Threads will get names depending on this.
37 /// </summary>
38 private string _threadPoolName;
39
40 /// <summary>
36 /// If this field is not null then the performance counters are enabled 41 /// If this field is not null then the performance counters are enabled
37 /// and use the string as the name of the instance. 42 /// and use the string as the name of the instance.
38 /// </summary> 43 /// </summary>
@@ -46,6 +51,7 @@ namespace Amib.Threading
46 _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads; 51 _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
47 _maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads; 52 _maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
48 _threadPriority = SmartThreadPool.DefaultThreadPriority; 53 _threadPriority = SmartThreadPool.DefaultThreadPriority;
54 _threadPoolName = SmartThreadPool.DefaultThreadPoolName;
49 _pcInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName; 55 _pcInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
50 _stackSize = SmartThreadPool.DefaultStackSize; 56 _stackSize = SmartThreadPool.DefaultStackSize;
51 } 57 }
@@ -56,6 +62,7 @@ namespace Amib.Threading
56 _minWorkerThreads = stpStartInfo._minWorkerThreads; 62 _minWorkerThreads = stpStartInfo._minWorkerThreads;
57 _maxWorkerThreads = stpStartInfo._maxWorkerThreads; 63 _maxWorkerThreads = stpStartInfo._maxWorkerThreads;
58 _threadPriority = stpStartInfo._threadPriority; 64 _threadPriority = stpStartInfo._threadPriority;
65 _threadPoolName = stpStartInfo._threadPoolName;
59 _pcInstanceName = stpStartInfo._pcInstanceName; 66 _pcInstanceName = stpStartInfo._pcInstanceName;
60 _stackSize = stpStartInfo._stackSize; 67 _stackSize = stpStartInfo._stackSize;
61 } 68 }
@@ -84,6 +91,13 @@ namespace Amib.Threading
84 set { _threadPriority = value; } 91 set { _threadPriority = value; }
85 } 92 }
86 93
94 public virtual string ThreadPoolName
95 {
96 get { return _threadPoolName; }
97 set { _threadPoolName = value; }
98 }
99
100
87 public string PerformanceCounterInstanceName 101 public string PerformanceCounterInstanceName
88 { 102 {
89 get { return _pcInstanceName; } 103 get { return _pcInstanceName; }
diff --git a/ThirdParty/SmartThreadPool/SmartThreadPool.cs b/ThirdParty/SmartThreadPool/SmartThreadPool.cs
index 8c9d38b..2c061d7 100644
--- a/ThirdParty/SmartThreadPool/SmartThreadPool.cs
+++ b/ThirdParty/SmartThreadPool/SmartThreadPool.cs
@@ -135,6 +135,11 @@ namespace Amib.Threading
135 /// </summary> 135 /// </summary>
136 public const ThreadPriority DefaultThreadPriority = ThreadPriority.Normal; 136 public const ThreadPriority DefaultThreadPriority = ThreadPriority.Normal;
137 137
138 /// <summary>
139 /// The default thread pool name
140 /// </summary>
141 public const string DefaultThreadPoolName = "SmartThreadPool";
142
138 #endregion 143 #endregion
139 144
140 #region Member Variables 145 #region Member Variables
@@ -143,7 +148,7 @@ namespace Amib.Threading
143 /// Contains the name of this instance of SmartThreadPool. 148 /// Contains the name of this instance of SmartThreadPool.
144 /// Can be changed by the user. 149 /// Can be changed by the user.
145 /// </summary> 150 /// </summary>
146 private string _name = "SmartThreadPool"; 151 private string _name = DefaultThreadPoolName;
147 152
148 /// <summary> 153 /// <summary>
149 /// Hashtable of all the threads in the thread pool. 154 /// Hashtable of all the threads in the thread pool.
@@ -307,6 +312,7 @@ namespace Amib.Threading
307 312
308 private void Initialize() 313 private void Initialize()
309 { 314 {
315 Name = _stpStartInfo.ThreadPoolName;
310 ValidateSTPStartInfo(); 316 ValidateSTPStartInfo();
311 317
312 if (null != _stpStartInfo.PerformanceCounterInstanceName) 318 if (null != _stpStartInfo.PerformanceCounterInstanceName)
diff --git a/ThirdPartyLicenses/Bullet-XNA.txt b/ThirdPartyLicenses/Bullet-XNA.txt
new file mode 100644
index 0000000..5d8899b
--- /dev/null
+++ b/ThirdPartyLicenses/Bullet-XNA.txt
@@ -0,0 +1,23 @@
1/*
2 * C# / XNA port of Bullet (c) 2011 Mark Neale <xexuxjy@hotmail.com>
3 * http://code.google.com/p/bullet-xna/
4 *
5 * Bullet Continuous Collision Detection and Physics Library
6 * Copyright (c) 2003-2008 Erwin Coumans http://www.bulletphysics.com/
7 *
8 * This software is provided 'as-is', without any express or implied warranty.
9 * In no event will the authors be held liable for any damages arising from
10 * the use of this software.
11 *
12 * Permission is granted to anyone to use this software for any purpose,
13 * including commercial applications, and to alter it and redistribute it
14 * freely, subject to the following restrictions:
15 *
16 * 1. The origin of this software must not be misrepresented; you must not
17 * claim that you wrote the original software. If you use this software
18 * in a product, an acknowledgment in the product documentation would be
19 * appreciated but is not required.
20 * 2. Altered source versions must be plainly marked as such, and must not be
21 * misrepresented as being the original software.
22 * 3. This notice may not be removed or altered from any source distribution.
23 */ \ No newline at end of file
diff --git a/bin/BulletXNA.dll b/bin/BulletXNA.dll
new file mode 100644
index 0000000..bfaac4f
--- /dev/null
+++ b/bin/BulletXNA.dll
Binary files differ
diff --git a/bin/BulletXNA.pdb b/bin/BulletXNA.pdb
new file mode 100644
index 0000000..ecab22f
--- /dev/null
+++ b/bin/BulletXNA.pdb
Binary files differ
diff --git a/bin/HttpServer_OpenSim.pdb b/bin/HttpServer_OpenSim.pdb
index b9161e1..f56e891 100644
--- a/bin/HttpServer_OpenSim.pdb
+++ b/bin/HttpServer_OpenSim.pdb
Binary files differ
diff --git a/bin/HttpServer_OpenSim.xml b/bin/HttpServer_OpenSim.xml
index d31bcca..fa88fc7 100644
--- a/bin/HttpServer_OpenSim.xml
+++ b/bin/HttpServer_OpenSim.xml
@@ -4,922 +4,421 @@
4 <name>HttpServer_OpenSim</name> 4 <name>HttpServer_OpenSim</name>
5 </assembly> 5 </assembly>
6 <members> 6 <members>
7 <member name="T:HttpServer.Sessions.IHttpSessionStore"> 7 <member name="T:HttpServer.RealmHandler">
8 <summary>
9 A session store is used to store and load sessions on a media.
10 The default implementation (<see cref="T:HttpServer.Sessions.MemorySessionStore"/>) saves/retrieves sessions from memory.
11 </summary>
12 </member>
13 <member name="M:HttpServer.Sessions.IHttpSessionStore.Create">
14 <summary>
15 Creates a new http session with a generated id.
16 </summary>
17 <returns>A <see cref="T:HttpServer.Sessions.IHttpSession"/> object</returns>
18 </member>
19 <member name="M:HttpServer.Sessions.IHttpSessionStore.Create(System.String)">
20 <summary> 8 <summary>
21 Creates a new http session with a specific id 9 Delegate used to find a realm/domain.
22 </summary> 10 </summary>
23 <param name="id">Id used to identify the new cookie..</param> 11 <param name="domain"></param>
24 <returns>A <see cref="T:HttpServer.Sessions.IHttpSession"/> object.</returns> 12 <returns></returns>
25 <remarks> 13 <remarks>
26 Id should be generated by the store implementation if it's null or <see cref="F:System.String.Empty"/>. 14 Realms are used during HTTP Authentication
27 </remarks> 15 </remarks>
16 <seealso cref="T:HttpServer.Authentication.AuthenticationModule"/>
17 <seealso cref="T:HttpServer.Authentication.AuthenticationHandler"/>
28 </member> 18 </member>
29 <member name="M:HttpServer.Sessions.IHttpSessionStore.Load(System.String)"> 19 <member name="T:HttpServer.HttpServer">
30 <summary>
31 Load an existing session.
32 </summary>
33 <param name="sessionId">Session id (usually retrieved from a client side cookie).</param>
34 <returns>A session if found; otherwise null.</returns>
35 </member>
36 <member name="M:HttpServer.Sessions.IHttpSessionStore.Save(HttpServer.Sessions.IHttpSession)">
37 <summary>
38 Save an updated session to the store.
39 </summary>
40 <param name="session">Session id (usually retrieved from a client side cookie).</param>
41 <exception cref="T:System.ArgumentException">If Id property have not been specified.</exception>
42 </member>
43 <member name="M:HttpServer.Sessions.IHttpSessionStore.AddUnused(HttpServer.Sessions.IHttpSession)">
44 <summary>
45 We use the flyweight pattern which reuses small objects
46 instead of creating new each time.
47 </summary>
48 <param name="session">Unused session that should be reused next time Create is called.</param>
49 </member>
50 <member name="M:HttpServer.Sessions.IHttpSessionStore.Cleanup">
51 <summary>
52 Remove expired sessions
53 </summary>
54 </member>
55 <member name="M:HttpServer.Sessions.IHttpSessionStore.Remove(System.String)">
56 <summary>
57 Remove a session
58 </summary>
59 <param name="sessionId">id of the session.</param>
60 </member>
61 <member name="P:HttpServer.Sessions.IHttpSessionStore.Item(System.String)">
62 <summary>
63 Load a session from the store
64 </summary>
65 <param name="sessionId"></param>
66 <returns>null if session is not found.</returns>
67 </member>
68 <member name="P:HttpServer.Sessions.IHttpSessionStore.ExpireTime">
69 <summary>
70 Number of minutes before a session expires.
71 </summary>
72 <value>Default time is 20 minutes.</value>
73 </member>
74 <member name="T:HttpServer.IHttpRequest">
75 <summary>
76 Contains server side HTTP request information.
77 </summary>
78 </member>
79 <member name="M:HttpServer.IHttpRequest.AddHeader(System.String,System.String)">
80 <summary>
81 Called during parsing of a <see cref="T:HttpServer.IHttpRequest"/>.
82 </summary>
83 <param name="name">Name of the header, should not be URL encoded</param>
84 <param name="value">Value of the header, should not be URL encoded</param>
85 <exception cref="T:HttpServer.Exceptions.BadRequestException">If a header is incorrect.</exception>
86 </member>
87 <member name="M:HttpServer.IHttpRequest.AddToBody(System.Byte[],System.Int32,System.Int32)">
88 <summary> 20 <summary>
89 Add bytes to the body 21 A complete HTTP server, you need to add a module to it to be able to handle incoming requests.
90 </summary> 22 </summary>
91 <param name="bytes">buffer to read bytes from</param> 23 <example>
92 <param name="offset">where to start read</param> 24 <code>
93 <param name="length">number of bytes to read</param> 25 // this small example will add two web site modules, thus handling
94 <returns>Number of bytes actually read (same as length unless we got all body bytes).</returns> 26 // two different sites. In reality you should add Controller modules or something
95 <exception cref="T:System.InvalidOperationException">If body is not writable</exception> 27 // two the website modules to be able to handle different requests.
96 <exception cref="T:System.ArgumentNullException"><c>bytes</c> is null.</exception> 28 HttpServer server = new HttpServer();
97 <exception cref="T:System.ArgumentOutOfRangeException"><c>offset</c> is out of range.</exception> 29 server.Add(new WebSiteModule("www.gauffin.com", "Gauffin Telecom AB"));
30 server.Add(new WebSiteModule("www.vapadi.se", "Remote PBX"));
31
32 // start regular http
33 server.Start(IPAddress.Any, 80);
34
35 // start https
36 server.Start(IPAddress.Any, 443, myCertificate);
37 </code>
38 </example>
39 <seealso cref="T:HttpServer.HttpModules.HttpModule"/>
40 <seealso cref="T:HttpServer.HttpModules.FileModule"/>
41 <seealso cref="T:HttpServer.HttpListener"/>
98 </member> 42 </member>
99 <member name="M:HttpServer.IHttpRequest.Clear"> 43 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.IComponentProvider)">
100 <summary> 44 <summary>
101 Clear everything in the request 45 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class.
102 </summary> 46 </summary>
47 <param name="provider">Used to get all components used in the server..</param>
103 </member> 48 </member>
104 <member name="M:HttpServer.IHttpRequest.DecodeBody(HttpServer.FormDecoders.FormDecoderProvider)"> 49 <member name="M:HttpServer.HttpServer.#ctor">
105 <summary> 50 <summary>
106 Decode body into a form. 51 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class.
107 </summary> 52 </summary>
108 <param name="providers">A list with form decoders.</param>
109 <exception cref="T:System.IO.InvalidDataException">If body contents is not valid for the chosen decoder.</exception>
110 <exception cref="T:System.InvalidOperationException">If body is still being transferred.</exception>
111 </member> 53 </member>
112 <member name="M:HttpServer.IHttpRequest.SetCookies(HttpServer.RequestCookies)"> 54 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.FormDecoders.FormDecoderProvider)">
113 <summary> 55 <summary>
114 Sets the cookies. 56 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class.
115 </summary> 57 </summary>
116 <param name="cookies">The cookies.</param> 58 <param name="decoderProvider">Form decoders are used to convert different types of posted data to the <see cref="T:HttpServer.HttpInput"/> object types.</param>
59 <seealso cref="T:HttpServer.FormDecoders.IFormDecoder"/>
60 <seealso cref="P:HttpServer.HttpServer.FormDecoderProviders"/>
117 </member> 61 </member>
118 <member name="M:HttpServer.IHttpRequest.CreateResponse(HttpServer.IHttpClientContext)"> 62 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.Sessions.IHttpSessionStore)">
119 <summary> 63 <summary>
120 Create a response object. 64 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class.
121 </summary> 65 </summary>
122 <param name="context">Context for the connected client.</param> 66 <param name="sessionStore">A session store is used to save and retrieve sessions</param>
123 <returns>A new <see cref="T:HttpServer.IHttpResponse"/>.</returns> 67 <seealso cref="T:HttpServer.Sessions.IHttpSessionStore"/>
124 </member> 68 </member>
125 <member name="P:HttpServer.IHttpRequest.AcceptTypes"> 69 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.ILogWriter)">
126 <summary> 70 <summary>
127 Gets kind of types accepted by the client. 71 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class.
128 </summary> 72 </summary>
73 <param name="logWriter">The log writer.</param>
74 <seealso cref="P:HttpServer.HttpServer.LogWriter"/>
129 </member> 75 </member>
130 <member name="P:HttpServer.IHttpRequest.Body"> 76 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.FormDecoders.FormDecoderProvider,HttpServer.ILogWriter)">
131 <summary> 77 <summary>
132 Gets or sets body stream. 78 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class.
133 </summary> 79 </summary>
80 <param name="decoderProvider">Form decoders are used to convert different types of posted data to the <see cref="T:HttpServer.HttpInput"/> object types.</param>
81 <param name="logWriter">The log writer.</param>
82 <seealso cref="T:HttpServer.FormDecoders.IFormDecoder"/>
83 <seealso cref="P:HttpServer.HttpServer.FormDecoderProviders"/>
84 <seealso cref="P:HttpServer.HttpServer.LogWriter"/>
134 </member> 85 </member>
135 <member name="P:HttpServer.IHttpRequest.BodyIsComplete"> 86 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.FormDecoders.FormDecoderProvider,HttpServer.Sessions.IHttpSessionStore,HttpServer.ILogWriter)">
136 <summary> 87 <summary>
137 Gets whether the body is complete. 88 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class.
138 </summary> 89 </summary>
90 <param name="decoderProvider">Form decoders are used to convert different types of posted data to the <see cref="T:HttpServer.HttpInput"/> object types.</param>
91 <param name="sessionStore">A session store is used to save and retrieve sessions</param>
92 <param name="logWriter">The log writer.</param>
93 <seealso cref="T:HttpServer.FormDecoders.IFormDecoder"/>
94 <seealso cref="P:HttpServer.HttpServer.FormDecoderProviders"/>
95 <seealso cref="P:HttpServer.HttpServer.LogWriter"/>
96 <seealso cref="T:HttpServer.Sessions.IHttpSessionStore"/>
139 </member> 97 </member>
140 <member name="P:HttpServer.IHttpRequest.Connection"> 98 <member name="M:HttpServer.HttpServer.Add(HttpServer.Rules.IRule)">
141 <summary> 99 <summary>
142 Gets or sets kind of connection used for the session. 100 Adds the specified rule.
143 </summary> 101 </summary>
102 <param name="rule">The rule.</param>
144 </member> 103 </member>
145 <member name="P:HttpServer.IHttpRequest.ContentLength"> 104 <member name="M:HttpServer.HttpServer.Add(HttpServer.HttpModules.HttpModule)">
146 <summary> 105 <summary>
147 Gets or sets number of bytes in the body. 106 Add a <see cref="T:HttpServer.HttpModules.HttpModule"/> to the server.
148 </summary> 107 </summary>
108 <param name="module">mode to add</param>
149 </member> 109 </member>
150 <member name="P:HttpServer.IHttpRequest.Cookies"> 110 <member name="M:HttpServer.HttpServer.DecodeBody(HttpServer.IHttpRequest)">
151 <summary> 111 <summary>
152 Gets cookies that was sent with the request. 112 Decodes the request body.
153 </summary> 113 </summary>
114 <param name="request">The request.</param>
115 <exception cref="T:HttpServer.Exceptions.InternalServerException">Failed to decode form data.</exception>
154 </member> 116 </member>
155 <member name="P:HttpServer.IHttpRequest.Form"> 117 <member name="M:HttpServer.HttpServer.ErrorPage(HttpServer.IHttpResponse,System.Net.HttpStatusCode,System.String)">
156 <summary> 118 <summary>
157 Gets form parameters. 119 Generate a HTTP error page (that will be added to the response body).
120 response status code is also set.
158 </summary> 121 </summary>
122 <param name="response">Response that the page will be generated in.</param>
123 <param name="error"><see cref="T:System.Net.HttpStatusCode"/>.</param>
124 <param name="body">response body contents.</param>
159 </member> 125 </member>
160 <member name="P:HttpServer.IHttpRequest.Headers"> 126 <member name="M:HttpServer.HttpServer.ErrorPage(HttpServer.IHttpResponse,HttpServer.Exceptions.HttpException)">
161 <summary> 127 <summary>
162 Gets headers sent by the client. 128 Generate a HTTP error page (that will be added to the response body).
129 response status code is also set.
163 </summary> 130 </summary>
131 <param name="response">Response that the page will be generated in.</param>
132 <param name="err">exception.</param>
164 </member> 133 </member>
165 <member name="P:HttpServer.IHttpRequest.HttpVersion"> 134 <member name="M:HttpServer.HttpServer.GetRealm(HttpServer.IHttpRequest)">
166 <summary> 135 <summary>
167 Gets or sets version of HTTP protocol that's used. 136 Realms are used by the <see cref="T:HttpServer.Authentication.AuthenticationModule"/>s.
168 </summary> 137 </summary>
169 <remarks> 138 <param name="request">HTTP request</param>
170 Probably <see cref="F:HttpServer.HttpHelper.HTTP10"/> or <see cref="F:HttpServer.HttpHelper.HTTP11"/>. 139 <returns>domain/realm.</returns>
171 </remarks>
172 <seealso cref="T:HttpServer.HttpHelper"/>
173 </member> 140 </member>
174 <member name="P:HttpServer.IHttpRequest.IsAjax"> 141 <member name="M:HttpServer.HttpServer.HandleRequest(HttpServer.IHttpClientContext,HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)">
175 <summary> 142 <summary>
176 Gets whether the request was made by Ajax (Asynchronous JavaScript) 143 Process an incoming request.
177 </summary> 144 </summary>
145 <param name="context">connection to client</param>
146 <param name="request">request information</param>
147 <param name="response">response that should be filled</param>
148 <param name="session">session information</param>
178 </member> 149 </member>
179 <member name="P:HttpServer.IHttpRequest.Method"> 150 <member name="M:HttpServer.HttpServer.OnClientDisconnected(HttpServer.IHttpClientContext,System.Net.Sockets.SocketError)">
180 <summary> 151 <summary>
181 Gets or sets requested method. 152 Can be overloaded to implement stuff when a client have been connected.
182 </summary> 153 </summary>
183 <remarks> 154 <remarks>
184 Will always be in upper case. 155 Default implementation does nothing.
185 </remarks> 156 </remarks>
186 <see cref="P:HttpServer.IHttpRequest.Method"/> 157 <param name="client">client that disconnected</param>
187 </member> 158 <param name="error">disconnect reason</param>
188 <member name="P:HttpServer.IHttpRequest.Param">
189 <summary>
190 Gets parameter from <see cref="P:HttpServer.IHttpRequest.QueryString"/> or <see cref="P:HttpServer.IHttpRequest.Form"/>.
191 </summary>
192 </member>
193 <member name="P:HttpServer.IHttpRequest.QueryString">
194 <summary>
195 Gets variables sent in the query string
196 </summary>
197 </member>
198 <member name="P:HttpServer.IHttpRequest.Uri">
199 <summary>
200 Gets or sets requested URI.
201 </summary>
202 </member> 159 </member>
203 <member name="P:HttpServer.IHttpRequest.UriParts"> 160 <member name="M:HttpServer.HttpServer.ProcessAuthentication(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)">
204 <summary> 161 <summary>
205 Gets URI absolute path divided into parts. 162 Handle authentication
206 </summary> 163 </summary>
207 <example> 164 <param name="request"></param>
208 // URI is: http://gauffin.com/code/tiny/ 165 <param name="response"></param>
209 Console.WriteLine(request.UriParts[0]); // result: code 166 <param name="session"></param>
210 Console.WriteLine(request.UriParts[1]); // result: tiny 167 <returns>true if request can be handled; false if not.</returns>
211 </example> 168 <exception cref="T:HttpServer.Exceptions.BadRequestException">Invalid authorization header</exception>
212 <remarks>
213 If you're using controllers than the first part is controller name,
214 the second part is method name and the third part is Id property.
215 </remarks>
216 <seealso cref="P:HttpServer.IHttpRequest.Uri"/>
217 </member> 169 </member>
218 <member name="P:HttpServer.IHttpRequest.UriPath"> 170 <member name="M:HttpServer.HttpServer.RequestAuthentication(HttpServer.Authentication.AuthenticationModule,HttpServer.IHttpRequest,HttpServer.IHttpResponse)">
219 <summary> 171 <summary>
220 Gets or sets path and query. 172 Will request authentication.
221 </summary> 173 </summary>
222 <see cref="P:HttpServer.IHttpRequest.Uri"/>
223 <remarks> 174 <remarks>
224 Are only used during request parsing. Cannot be set after "Host" header have been 175 Sends respond to client, nothing else can be done with the response after this.
225 added.
226 </remarks> 176 </remarks>
177 <param name="mod"></param>
178 <param name="request"></param>
179 <param name="response"></param>
227 </member> 180 </member>
228 <member name="T:HttpServer.IHttpContextHandler"> 181 <member name="M:HttpServer.HttpServer.OnRequest(System.Object,HttpServer.RequestEventArgs)">
229 <summary>
230 Class that receives Requests from a <see cref="T:HttpServer.IHttpClientContext"/>.
231 </summary>
232 </member>
233 <member name="M:HttpServer.IHttpContextHandler.ClientDisconnected(HttpServer.IHttpClientContext,System.Net.Sockets.SocketError)">
234 <summary>
235 Client have been disconnected.
236 </summary>
237 <param name="client">Client that was disconnected.</param>
238 <param name="error">Reason</param>
239 <see cref="T:HttpServer.IHttpClientContext"/>
240 </member>
241 <member name="M:HttpServer.IHttpContextHandler.RequestReceived(HttpServer.IHttpClientContext,HttpServer.IHttpRequest)">
242 <summary>
243 Invoked when a client context have received a new HTTP request
244 </summary>
245 <param name="client">Client that received the request.</param>
246 <param name="request">Request that was received.</param>
247 <see cref="T:HttpServer.IHttpClientContext"/>
248 </member>
249 <member name="T:HttpServer.Helpers.GetIdTitle">
250 <summary>
251 Delegate used by <see cref="M:HttpServer.Helpers.FormHelper.Select(System.String,System.Collections.IEnumerable,HttpServer.Helpers.GetIdTitle,System.Object,System.Boolean)"/> to populate select options.
252 </summary>
253 <param name="obj">current object (for instance a User).</param>
254 <param name="id">Text that should be displayed in the value part of a &lt;optiongt;-tag.</param>
255 <param name="title">Text shown in the select list.</param>
256 <example>
257 // Class that is going to be used in a SELECT-tag.
258 public class User
259 {
260 private readonly string _realName;
261 private readonly int _id;
262 public User(int id, string realName)
263 {
264 _id = id;
265 _realName = realName;
266 }
267 public string RealName
268 {
269 get { return _realName; }
270 }
271
272 public int Id
273 {
274 get { return _id; }
275 }
276 }
277
278 // Using an inline delegate to generate the select list
279 public void UserInlineDelegate()
280 {
281 List&lt;User&gt; items = new List&lt;User&gt;();
282 items.Add(new User(1, "adam"));
283 items.Add(new User(2, "bertial"));
284 items.Add(new User(3, "david"));
285 string htmlSelect = Select("users", "users", items, delegate(object o, out object id, out object value)
286 {
287 User user = (User)o;
288 id = user.Id;
289 value = user.RealName;
290 }, 2, true);
291 }
292
293 // Using an method as delegate to generate the select list.
294 public void UseExternalDelegate()
295 {
296 List&lt;User&gt; items = new List&lt;User&gt;();
297 items.Add(new User(1, "adam"));
298 items.Add(new User(2, "bertial"));
299 items.Add(new User(3, "david"));
300 string htmlSelect = Select("users", "users", items, UserOptions, 1, true);
301 }
302
303 // delegate returning id and title
304 public static void UserOptions(object o, out object id, out object title)
305 {
306 User user = (User)o;
307 id = user.Id;
308 value = user.RealName;
309 } /// </example>
310 </member>
311 <member name="T:HttpServer.Exceptions.ForbiddenException">
312 <summary>
313 The server understood the request, but is refusing to fulfill it.
314 Authorization will not help and the request SHOULD NOT be repeated.
315 If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled,
316 it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information
317 available to the client, the status code 404 (Not Found) can be used instead.
318
319 Text taken from: http://www.submissionchamber.com/help-guides/error-codes.php
320 </summary>
321 </member>
322 <member name="T:HttpServer.Exceptions.HttpException">
323 <summary>
324 All HTTP based exceptions will derive this class.
325 </summary>
326 </member>
327 <member name="M:HttpServer.Exceptions.HttpException.#ctor(System.Net.HttpStatusCode,System.String)">
328 <summary>
329 Create a new HttpException
330 </summary>
331 <param name="code">http status code (sent in the response)</param>
332 <param name="message">error description</param>
333 </member>
334 <member name="M:HttpServer.Exceptions.HttpException.#ctor(System.Net.HttpStatusCode,System.String,System.Exception)">
335 <summary>
336 Create a new HttpException
337 </summary>
338 <param name="code">http status code (sent in the response)</param>
339 <param name="message">error description</param>
340 <param name="inner">inner exception</param>
341 </member>
342 <member name="P:HttpServer.Exceptions.HttpException.HttpStatusCode">
343 <summary>
344 status code to use in the response.
345 </summary>
346 </member>
347 <member name="M:HttpServer.Exceptions.ForbiddenException.#ctor(System.String)">
348 <summary>
349 Initializes a new instance of the <see cref="T:HttpServer.Exceptions.ForbiddenException"/> class.
350 </summary>
351 <param name="errorMsg">error message</param>
352 </member>
353 <member name="T:HttpServer.Sessions.MemorySession">
354 <summary>
355 A session stored in memory.
356 </summary>
357 </member>
358 <member name="T:HttpServer.Sessions.IHttpSession">
359 <summary>
360 Interface for sessions
361 </summary>
362 </member>
363 <member name="M:HttpServer.Sessions.IHttpSession.Clear">
364 <summary>
365 Remove everything from the session
366 </summary>
367 </member>
368 <member name="M:HttpServer.Sessions.IHttpSession.Clear(System.Boolean)">
369 <summary>
370 Remove everything from the session
371 </summary>
372 <param name="expires">True if the session is cleared due to expiration</param>
373 </member>
374 <member name="P:HttpServer.Sessions.IHttpSession.Id">
375 <summary>
376 Session id
377 </summary>
378 </member>
379 <member name="P:HttpServer.Sessions.IHttpSession.Item(System.String)">
380 <summary>
381 Should
382 </summary>
383 <param name="name">Name of the session variable</param>
384 <returns>null if it's not set</returns>
385 <exception cref="T:System.Runtime.Serialization.SerializationException">If the object cant be serialized.</exception>
386 </member>
387 <member name="P:HttpServer.Sessions.IHttpSession.Accessed">
388 <summary>
389 When the session was last accessed.
390 This property is touched by the http server each time the
391 session is requested.
392 </summary>
393 </member>
394 <member name="P:HttpServer.Sessions.IHttpSession.Count">
395 <summary>
396 Number of session variables.
397 </summary>
398 </member>
399 <member name="E:HttpServer.Sessions.IHttpSession.BeforeClear">
400 <summary>
401 Event triggered upon clearing the session
402 </summary>
403 </member>
404 <member name="M:HttpServer.Sessions.MemorySession.#ctor(System.String)">
405 <summary> 182 <summary>
406 183 Received from a <see cref="T:HttpServer.IHttpClientContext"/> when a request have been parsed successfully.
407 </summary> 184 </summary>
408 <param name="id">A unique id used by the sessions store to identify the session</param> 185 <param name="source"><see cref="T:HttpServer.IHttpClientContext"/> that received the request.</param>
186 <param name="args">The request.</param>
409 </member> 187 </member>
410 <member name="M:HttpServer.Sessions.MemorySession.SetId(System.String)"> 188 <member name="M:HttpServer.HttpServer.ProcessRequestWrapper(HttpServer.IHttpClientContext,HttpServer.IHttpRequest)">
411 <summary> 189 <summary>
412 Id 190 To be able to track request count.
413 </summary> 191 </summary>
414 <param name="id"></param> 192 <param name="context"></param>
193 <param name="request"></param>
415 </member> 194 </member>
416 <member name="M:HttpServer.Sessions.MemorySession.Clear"> 195 <member name="M:HttpServer.HttpServer.Start(System.Net.IPAddress,System.Int32)">
417 <summary> 196 <summary>
418 Remove everything from the session 197 Start the web server using regular HTTP.
419 </summary> 198 </summary>
199 <param name="address">IP Address to listen on, use <c>IpAddress.Any </c>to accept connections on all IP addresses/network cards.</param>
200 <param name="port">Port to listen on. 80 can be a good idea =)</param>
201 <exception cref="T:System.ArgumentNullException"><c>address</c> is null.</exception>
202 <exception cref="T:System.ArgumentException">Port must be a positive number.</exception>
420 </member> 203 </member>
421 <member name="M:HttpServer.Sessions.MemorySession.Clear(System.Boolean)"> 204 <member name="M:HttpServer.HttpServer.Start(System.Net.IPAddress,System.Int32,System.Security.Cryptography.X509Certificates.X509Certificate)">
422 <summary> 205 <summary>
423 Clears the specified expire. 206 Accept secure connections.
424 </summary> 207 </summary>
425 <param name="expires">True if the session is cleared due to expiration</param> 208 <param name="address">IP Address to listen on, use <see cref="F:System.Net.IPAddress.Any"/> to accept connections on all IP Addresses / network cards.</param>
209 <param name="port">Port to listen on. 80 can be a good idea =)</param>
210 <param name="certificate">Certificate to use</param>
211 <exception cref="T:System.ArgumentNullException"><c>address</c> is null.</exception>
212 <exception cref="T:System.ArgumentException">Port must be a positive number.</exception>
426 </member> 213 </member>
427 <member name="M:HttpServer.Sessions.MemorySession.Dispose"> 214 <member name="M:HttpServer.HttpServer.Stop">
428 <summary> 215 <summary>
429 Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 216 shut down the server and listeners
430 </summary> 217 </summary>
431 <filterpriority>2</filterpriority>
432 </member> 218 </member>
433 <member name="P:HttpServer.Sessions.MemorySession.Id"> 219 <member name="M:HttpServer.HttpServer.WriteLog(HttpServer.LogPrio,System.String)">
434 <summary> 220 <summary>
435 Session id 221 write an entry to the log file
436 </summary> 222 </summary>
223 <param name="prio">importance of the message</param>
224 <param name="message">log message</param>
437 </member> 225 </member>
438 <member name="P:HttpServer.Sessions.MemorySession.Item(System.String)"> 226 <member name="M:HttpServer.HttpServer.WriteLog(System.Object,HttpServer.LogPrio,System.String)">
439 <summary> 227 <summary>
440 Should 228 write an entry to the log file
441 </summary> 229 </summary>
442 <param name="name">Name of the session variable</param> 230 <param name="source">object that wrote the message</param>
443 <returns>null if it's not set</returns> 231 <param name="prio">importance of the message</param>
232 <param name="message">log message</param>
444 </member> 233 </member>
445 <member name="P:HttpServer.Sessions.MemorySession.Accessed"> 234 <member name="P:HttpServer.HttpServer.Current">
446 <summary> 235 <summary>
447 when the session was last accessed. 236 Server that is handling the current request.
448 </summary> 237 </summary>
449 <remarks> 238 <remarks>
450 Used to determine when the session should be removed. 239 Will be set as soon as a request arrives to the <see cref="T:HttpServer.HttpServer"/> object.
451 </remarks> 240 </remarks>
452 </member> 241 </member>
453 <member name="P:HttpServer.Sessions.MemorySession.Count"> 242 <member name="P:HttpServer.HttpServer.AuthenticationModules">
454 <summary>
455 Number of values in the session
456 </summary>
457 </member>
458 <member name="P:HttpServer.Sessions.MemorySession.Changed">
459 <summary>
460 Flag to indicate that the session have been changed
461 and should be saved into the session store.
462 </summary>
463 </member>
464 <member name="E:HttpServer.Sessions.MemorySession.BeforeClear">
465 <summary>
466 Event triggered upon clearing the session
467 </summary>
468 </member>
469 <member name="T:HttpServer.ResponseCookie">
470 <summary>
471 cookie being sent back to the browser.
472 </summary>
473 <seealso cref="T:HttpServer.ResponseCookie"/>
474 </member>
475 <member name="T:HttpServer.RequestCookie">
476 <summary>
477 cookie sent by the client/browser
478 </summary>
479 <seealso cref="T:HttpServer.ResponseCookie"/>
480 </member>
481 <member name="M:HttpServer.RequestCookie.#ctor(System.String,System.String)">
482 <summary>
483 Constructor.
484 </summary>
485 <param name="id">cookie identifier</param>
486 <param name="content">cookie content</param>
487 <exception cref="T:System.ArgumentNullException">id or content is null</exception>
488 <exception cref="T:System.ArgumentException">id is empty</exception>
489 </member>
490 <member name="M:HttpServer.RequestCookie.ToString">
491 <summary>
492 Gets the cookie HTML representation.
493 </summary>
494 <returns>cookie string</returns>
495 </member>
496 <member name="P:HttpServer.RequestCookie.Name">
497 <summary>
498 Gets the cookie identifier.
499 </summary>
500 </member>
501 <member name="P:HttpServer.RequestCookie.Value">
502 <summary>
503 Cookie value. Set to null to remove cookie.
504 </summary>
505 </member>
506 <member name="M:HttpServer.ResponseCookie.#ctor(System.String,System.String,System.DateTime)">
507 <summary>
508 Constructor.
509 </summary>
510 <param name="id">cookie identifier</param>
511 <param name="content">cookie content</param>
512 <param name="expiresAt">cookie expiration date. Use DateTime.MinValue for session cookie.</param>
513 <exception cref="T:System.ArgumentNullException">id or content is null</exception>
514 <exception cref="T:System.ArgumentException">id is empty</exception>
515 </member>
516 <member name="M:HttpServer.ResponseCookie.#ctor(System.String,System.String,System.DateTime,System.String,System.String)">
517 <summary>
518 Create a new cookie
519 </summary>
520 <param name="name">name identifying the cookie</param>
521 <param name="value">cookie value</param>
522 <param name="expires">when the cookie expires. Setting DateTime.MinValue will delete the cookie when the session is closed.</param>
523 <param name="path">Path to where the cookie is valid</param>
524 <param name="domain">Domain that the cookie is valid for.</param>
525 </member>
526 <member name="M:HttpServer.ResponseCookie.#ctor(HttpServer.RequestCookie,System.DateTime)">
527 <summary>
528 Create a new cookie
529 </summary>
530 <param name="cookie">Name and value will be used</param>
531 <param name="expires">when the cookie expires.</param>
532 </member>
533 <member name="M:HttpServer.ResponseCookie.ToString">
534 <summary>
535 Gets the cookie HTML representation.
536 </summary>
537 <returns>cookie string</returns>
538 </member>
539 <member name="P:HttpServer.ResponseCookie.Expires">
540 <summary>
541 When the cookie expires.
542 DateTime.MinValue means that the cookie expires when the session do so.
543 </summary>
544 </member>
545 <member name="P:HttpServer.ResponseCookie.Path">
546 <summary>
547 Cookie is only valid under this path.
548 </summary>
549 </member>
550 <member name="T:HttpServer.IHttpClientContext">
551 <summary>
552 Contains a connection to a browser/client.
553 </summary>
554 </member>
555 <member name="M:HttpServer.IHttpClientContext.Disconnect(System.Net.Sockets.SocketError)">
556 <summary>
557 Disconnect from client
558 </summary>
559 <param name="error">error to report in the <see cref="E:HttpServer.IHttpClientContext.Disconnected"/> event.</param>
560 </member>
561 <member name="M:HttpServer.IHttpClientContext.Respond(System.String,System.Net.HttpStatusCode,System.String,System.String,System.String)">
562 <summary>
563 Send a response.
564 </summary>
565 <param name="httpVersion">Either <see cref="F:HttpServer.HttpHelper.HTTP10"/> or <see cref="F:HttpServer.HttpHelper.HTTP11"/></param>
566 <param name="statusCode">HTTP status code</param>
567 <param name="reason">reason for the status code.</param>
568 <param name="body">HTML body contents, can be null or empty.</param>
569 <param name="contentType">A content type to return the body as, i.e. 'text/html' or 'text/plain', defaults to 'text/html' if null or empty</param>
570 <exception cref="T:System.ArgumentException">If <paramref name="httpVersion"/> is invalid.</exception>
571 </member>
572 <member name="M:HttpServer.IHttpClientContext.Respond(System.String,System.Net.HttpStatusCode,System.String)">
573 <summary>
574 Send a response.
575 </summary>
576 <param name="httpVersion">Either <see cref="F:HttpServer.HttpHelper.HTTP10"/> or <see cref="F:HttpServer.HttpHelper.HTTP11"/></param>
577 <param name="statusCode">HTTP status code</param>
578 <param name="reason">reason for the status code.</param>
579 </member>
580 <member name="M:HttpServer.IHttpClientContext.Respond(System.String)">
581 <summary>
582 Send a response.
583 </summary>
584 <exception cref="T:System.ArgumentNullException"></exception>
585 </member>
586 <member name="M:HttpServer.IHttpClientContext.Send(System.Byte[])">
587 <summary>
588 send a whole buffer
589 </summary>
590 <param name="buffer">buffer to send</param>
591 <exception cref="T:System.ArgumentNullException"></exception>
592 </member>
593 <member name="M:HttpServer.IHttpClientContext.Send(System.Byte[],System.Int32,System.Int32)">
594 <summary>
595 Send data using the stream
596 </summary>
597 <param name="buffer">Contains data to send</param>
598 <param name="offset">Start position in buffer</param>
599 <param name="size">number of bytes to send</param>
600 <exception cref="T:System.ArgumentNullException"></exception>
601 <exception cref="T:System.ArgumentOutOfRangeException"></exception>
602 </member>
603 <member name="M:HttpServer.IHttpClientContext.Close">
604 <summary>
605 Closes the streams and disposes of the unmanaged resources
606 </summary>
607 </member>
608 <member name="P:HttpServer.IHttpClientContext.Secured">
609 <summary> 243 <summary>
610 Using SSL or other encryption method. 244 Modules used for authentication. The module that is is added first is used as
245 the default authentication module.
611 </summary> 246 </summary>
247 <remarks>Use the corresponding property
248 in the <see cref="T:HttpServer.HttpModules.WebSiteModule"/> if you are using multiple websites.</remarks>
612 </member> 249 </member>
613 <member name="P:HttpServer.IHttpClientContext.IsSecured"> 250 <member name="P:HttpServer.HttpServer.FormDecoderProviders">
614 <summary> 251 <summary>
615 Using SSL or other encryption method. 252 Form decoder providers are used to decode request body (which normally contains form data).
616 </summary> 253 </summary>
617 </member> 254 </member>
618 <member name="E:HttpServer.IHttpClientContext.Disconnected"> 255 <member name="P:HttpServer.HttpServer.ServerName">
619 <summary> 256 <summary>
620 The context have been disconnected. 257 Server name sent in HTTP responses.
621 </summary> 258 </summary>
622 <remarks> 259 <remarks>
623 Event can be used to clean up a context, or to reuse it. 260 Do NOT include version in name, since it makes it
261 easier for hackers.
624 </remarks> 262 </remarks>
625 </member> 263 </member>
626 <member name="E:HttpServer.IHttpClientContext.RequestReceived"> 264 <member name="P:HttpServer.HttpServer.SessionCookieName">
627 <summary>
628 A request have been received in the context.
629 </summary>
630 </member>
631 <member name="T:HttpServer.DisconnectedEventArgs">
632 <summary>
633 A <see cref="T:HttpServer.IHttpClientContext"/> have been disconnected.
634 </summary>
635 </member>
636 <member name="M:HttpServer.DisconnectedEventArgs.#ctor(System.Net.Sockets.SocketError)">
637 <summary>
638 Initializes a new instance of the <see cref="T:HttpServer.DisconnectedEventArgs"/> class.
639 </summary>
640 <param name="error">Reason to disconnection.</param>
641 </member>
642 <member name="P:HttpServer.DisconnectedEventArgs.Error">
643 <summary>
644 Gets reason to why client disconnected.
645 </summary>
646 </member>
647 <member name="T:HttpServer.RequestEventArgs">
648 <summary>
649
650 </summary>
651 </member>
652 <member name="M:HttpServer.RequestEventArgs.#ctor(HttpServer.IHttpRequest)">
653 <summary>
654 Initializes a new instance of the <see cref="T:HttpServer.RequestEventArgs"/> class.
655 </summary>
656 <param name="request">The request.</param>
657 </member>
658 <member name="P:HttpServer.RequestEventArgs.Request">
659 <summary>
660 Gets received request.
661 </summary>
662 </member>
663 <member name="T:HttpServer.HttpListenerBase">
664 <summary>
665 Contains a listener that doesn't do anything with the connections.
666 </summary>
667 </member>
668 <member name="M:HttpServer.HttpListenerBase.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory)">
669 <summary>
670 Listen for regular HTTP connections
671 </summary>
672 <param name="address">IP Address to accept connections on</param>
673 <param name="port">TCP Port to listen on, default HTTP port is 80.</param>
674 <param name="factory">Factory used to create <see cref="T:HttpServer.IHttpClientContext"/>es.</param>
675 <exception cref="T:System.ArgumentNullException"><c>address</c> is null.</exception>
676 <exception cref="T:System.ArgumentException">Port must be a positive number.</exception>
677 </member>
678 <member name="M:HttpServer.HttpListenerBase.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory,System.Security.Cryptography.X509Certificates.X509Certificate)">
679 <summary>
680 Initializes a new instance of the <see cref="T:HttpServer.HttpListenerBase"/> class.
681 </summary>
682 <param name="address">IP Address to accept connections on</param>
683 <param name="port">TCP Port to listen on, default HTTPS port is 443</param>
684 <param name="factory">Factory used to create <see cref="T:HttpServer.IHttpClientContext"/>es.</param>
685 <param name="certificate">Certificate to use</param>
686 </member>
687 <member name="M:HttpServer.HttpListenerBase.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory,System.Security.Cryptography.X509Certificates.X509Certificate,System.Security.Authentication.SslProtocols)">
688 <summary>
689 Initializes a new instance of the <see cref="T:HttpServer.HttpListenerBase"/> class.
690 </summary>
691 <param name="address">IP Address to accept connections on</param>
692 <param name="port">TCP Port to listen on, default HTTPS port is 443</param>
693 <param name="factory">Factory used to create <see cref="T:HttpServer.IHttpClientContext"/>es.</param>
694 <param name="certificate">Certificate to use</param>
695 <param name="protocol">which HTTPS protocol to use, default is TLS.</param>
696 </member>
697 <member name="M:HttpServer.HttpListenerBase.OnAccept(System.IAsyncResult)">
698 <exception cref="T:System.Exception"><c>Exception</c>.</exception>
699 </member>
700 <member name="M:HttpServer.HttpListenerBase.RetryBeginAccept">
701 <summary> 265 <summary>
702 Will try to accept connections one more time. 266 Name of cookie where session id is stored.
703 </summary> 267 </summary>
704 <exception cref="T:System.Exception">If any exceptions is thrown.</exception>
705 </member> 268 </member>
706 <member name="M:HttpServer.HttpListenerBase.OnAcceptingSocket(System.Net.Sockets.Socket)"> 269 <member name="P:HttpServer.HttpServer.LogWriter">
707 <summary> 270 <summary>
708 Can be used to create filtering of new connections. 271 Specified where logging should go.
709 </summary> 272 </summary>
710 <param name="socket">Accepted socket</param> 273 <seealso cref="T:HttpServer.NullLogWriter"/>
711 <returns>true if connection can be accepted; otherwise false.</returns> 274 <seealso cref="T:HttpServer.ConsoleLogWriter"/>
275 <seealso cref="P:HttpServer.HttpServer.LogWriter"/>
712 </member> 276 </member>
713 <member name="M:HttpServer.HttpListenerBase.Start(System.Int32)"> 277 <member name="P:HttpServer.HttpServer.BackLog">
714 <summary> 278 <summary>
715 Start listen for new connections 279 Number of connections that can wait to be accepted by the server.
716 </summary> 280 </summary>
717 <param name="backlog">Number of connections that can stand in a queue to be accepted.</param> 281 <remarks>Default is 10.</remarks>
718 <exception cref="T:System.InvalidOperationException">Listener have already been started.</exception>
719 </member> 282 </member>
720 <member name="M:HttpServer.HttpListenerBase.Stop"> 283 <member name="P:HttpServer.HttpServer.MaxRequestCount">
721 <summary> 284 <summary>
722 Stop the listener 285 Gets or sets maximum number of allowed simultaneous requests.
723 </summary> 286 </summary>
724 <exception cref="T:System.Net.Sockets.SocketException"></exception> 287 <remarks>
288 <para>
289 This property is useful in busy systems. The HTTP server
290 will start queuing new requests if this limit is hit, instead
291 of trying to process all incoming requests directly.
292 </para>
293 <para>
294 The default number if allowed simultaneous requests are 10.
295 </para>
296 </remarks>
725 </member> 297 </member>
726 <member name="P:HttpServer.HttpListenerBase.LogWriter"> 298 <member name="P:HttpServer.HttpServer.MaxQueueSize">
727 <summary> 299 <summary>
728 Gives you a change to receive log entries for all internals of the HTTP library. 300 Gets or sets maximum number of requests queuing to be handled.
729 </summary> 301 </summary>
730 <remarks> 302 <remarks>
731 You may not switch log writer after starting the listener. 303 <para>
304 The WebServer will start turning requests away if response code
305 <see cref="F:System.Net.HttpStatusCode.ServiceUnavailable"/> to indicate that the server
306 is too busy to be able to handle the request.
307 </para>
732 </remarks> 308 </remarks>
733 </member> 309 </member>
734 <member name="P:HttpServer.HttpListenerBase.UseTraceLogs"> 310 <member name="E:HttpServer.HttpServer.RealmWanted">
735 <summary> 311 <summary>
736 True if we should turn on trace logs. 312 Realms are used during HTTP authentication.
313 Default realm is same as server name.
737 </summary> 314 </summary>
738 </member> 315 </member>
739 <member name="E:HttpServer.HttpListenerBase.ExceptionThrown"> 316 <member name="E:HttpServer.HttpServer.ExceptionThrown">
740 <summary> 317 <summary>
741 Catch exceptions not handled by the listener. 318 Let's to receive unhandled exceptions from the threads.
742 </summary> 319 </summary>
743 <remarks> 320 <remarks>
744 Exceptions will be thrown during debug mode if this event is not used, 321 Exceptions will be thrown during debug mode if this event is not used,
745 exceptions will be printed to console and suppressed during release mode. 322 exceptions will be printed to console and suppressed during release mode.
746 </remarks> 323 </remarks>
747 </member> 324 </member>
748 <member name="E:HttpServer.HttpListenerBase.RequestReceived"> 325 <member name="T:HttpServer.HttpModules.ResourceFileModule">
749 <summary> 326 <summary>
750 A request have been received from a <see cref="T:HttpServer.IHttpClientContext"/>. 327 Serves files that are stored in embedded resources.
751 </summary> 328 </summary>
752 </member> 329 </member>
753 <member name="T:HttpServer.FormDecoders.MultipartDecoder"> 330 <member name="T:HttpServer.HttpModules.HttpModule">
754 <summary> 331 <summary>
755 332 A HttpModule can be used to serve Uri's. The module itself
333 decides if it should serve a Uri or not. In this way, you can
334 get a very flexible http application since you can let multiple modules
335 serve almost similar urls.
756 </summary> 336 </summary>
757 <remarks> 337 <remarks>
758 http://www.faqs.org/rfcs/rfc1867.html 338 Throw <see cref="T:HttpServer.Exceptions.UnauthorizedException"/> if you are using a <see cref="T:HttpServer.Authentication.AuthenticationModule"/> and want to prompt for user name/password.
759 </remarks> 339 </remarks>
760 </member> 340 </member>
761 <member name="T:HttpServer.FormDecoders.IFormDecoder"> 341 <member name="M:HttpServer.HttpModules.HttpModule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)">
762 <summary>
763 Interface for form content decoders.
764 </summary>
765 </member>
766 <member name="M:HttpServer.FormDecoders.IFormDecoder.Decode(System.IO.Stream,System.String,System.Text.Encoding)">
767 <summary>
768
769 </summary>
770 <param name="stream">Stream containing the content</param>
771 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case</param>
772 <param name="encoding">Stream enconding</param>
773 <returns>A http form, or null if content could not be parsed.</returns>
774 <exception cref="T:System.IO.InvalidDataException">If contents in the stream is not valid input data.</exception>
775 </member>
776 <member name="M:HttpServer.FormDecoders.IFormDecoder.CanParse(System.String)">
777 <summary>
778 Checks if the decoder can handle the mime type
779 </summary>
780 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case.</param>
781 <returns>True if the decoder can parse the specified content type</returns>
782 </member>
783 <member name="F:HttpServer.FormDecoders.MultipartDecoder.MimeType">
784 <summary>
785 multipart/form-data
786 </summary>
787 </member>
788 <member name="F:HttpServer.FormDecoders.MultipartDecoder.FormData">
789 <summary>
790 form-data
791 </summary>
792 </member>
793 <member name="M:HttpServer.FormDecoders.MultipartDecoder.Decode(System.IO.Stream,System.String,System.Text.Encoding)">
794 <summary>
795
796 </summary>
797 <param name="stream">Stream containing the content</param>
798 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case</param>
799 <param name="encoding">Stream enconding</param>
800 <returns>A http form, or null if content could not be parsed.</returns>
801 <exception cref="T:System.IO.InvalidDataException">If contents in the stream is not valid input data.</exception>
802 <exception cref="T:System.ArgumentNullException">If any parameter is null</exception>
803 </member>
804 <member name="M:HttpServer.FormDecoders.MultipartDecoder.CanParse(System.String)">
805 <summary>
806 Checks if the decoder can handle the mime type
807 </summary>
808 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case.</param>
809 <returns>True if the decoder can parse the specified content type</returns>
810 </member>
811 <member name="T:HttpServer.Exceptions.NotFoundException">
812 <summary>
813 The requested resource was not found in the web server.
814 </summary>
815 </member>
816 <member name="M:HttpServer.Exceptions.NotFoundException.#ctor(System.String,System.Exception)">
817 <summary>
818 Create a new exception
819 </summary>
820 <param name="message">message describing the error</param>
821 <param name="inner">inner exception</param>
822 </member>
823 <member name="M:HttpServer.Exceptions.NotFoundException.#ctor(System.String)">
824 <summary>
825 Create a new exception
826 </summary>
827 <param name="message">message describing the error</param>
828 </member>
829 <member name="T:HttpServer.Authentication.AuthenticationHandler">
830 <summary> 342 <summary>
831 Delegate used to let authentication modules authenticate the user name and password. 343 Method that process the url
832 </summary> 344 </summary>
833 <param name="realm">Realm that the user want to authenticate in</param> 345 <param name="request">Information sent by the browser about the request</param>
834 <param name="userName">User name specified by client</param> 346 <param name="response">Information that is being sent back to the client.</param>
835 <param name="token">Can either be user password or implementation specific token.</param> 347 <param name="session">Session used to </param>
836 <param name="login">object that will be stored in a session variable called <see cref="F:HttpServer.Authentication.AuthenticationModule.AuthenticationTag"/> if authentication was successful.</param> 348 <returns>true if this module handled the request.</returns>
837 <exception cref="T:HttpServer.Exceptions.ForbiddenException">throw forbidden exception if too many attempts have been made.</exception>
838 <remarks>
839 <para>
840 Use <see cref="P:HttpServer.Authentication.DigestAuthentication.TokenIsHA1"/> to specify that the token is a HA1 token. (MD5 generated
841 string from realm, user name and password); Md5String(userName + ":" + realm + ":" + password);
842 </para>
843 </remarks>
844 </member> 349 </member>
845 <member name="T:HttpServer.Authentication.AuthenticationRequiredHandler"> 350 <member name="M:HttpServer.HttpModules.HttpModule.SetLogWriter(HttpServer.ILogWriter)">
846 <summary> 351 <summary>
847 Let's you decide on a system level if authentication is required. 352 Set the log writer to use.
848 </summary> 353 </summary>
849 <param name="request">HTTP request from client</param> 354 <param name="writer">logwriter to use.</param>
850 <returns>true if user should be authenticated.</returns>
851 <remarks>throw <see cref="T:HttpServer.Exceptions.ForbiddenException"/> if no more attempts are allowed.</remarks>
852 <exception cref="T:HttpServer.Exceptions.ForbiddenException">If no more attempts are allowed</exception>
853 </member> 355 </member>
854 <member name="T:HttpServer.Authentication.AuthenticationModule"> 356 <member name="M:HttpServer.HttpModules.HttpModule.Write(HttpServer.LogPrio,System.String)">
855 <summary> 357 <summary>
856 Authentication modules are used to implement different 358 Log something.
857 kind of HTTP authentication.
858 </summary> 359 </summary>
360 <param name="prio">importance of log message</param>
361 <param name="message">message</param>
859 </member> 362 </member>
860 <member name="F:HttpServer.Authentication.AuthenticationModule.AuthenticationTag"> 363 <member name="P:HttpServer.HttpModules.HttpModule.AllowSecondaryProcessing">
861 <summary> 364 <summary>
862 Tag used for authentication. 365 If true specifies that the module doesn't consume the processing of a request so that subsequent modules
366 can continue processing afterwards. Default is false.
863 </summary> 367 </summary>
864 </member> 368 </member>
865 <member name="M:HttpServer.Authentication.AuthenticationModule.#ctor(HttpServer.Authentication.AuthenticationHandler,HttpServer.Authentication.AuthenticationRequiredHandler)"> 369 <member name="M:HttpServer.HttpModules.ResourceFileModule.#ctor">
866 <summary> 370 <summary>
867 Initializes a new instance of the <see cref="T:HttpServer.Authentication.AuthenticationModule"/> class. 371 Initializes a new instance of the <see cref="T:HttpServer.HttpModules.ResourceFileModule"/> class.
372 Runs <see cref="M:HttpServer.HttpModules.ResourceFileModule.AddDefaultMimeTypes"/> to make sure the basic mime types are available, they can be cleared later
373 through the use of <see cref="P:HttpServer.HttpModules.ResourceFileModule.MimeTypes"/> if desired.
868 </summary> 374 </summary>
869 <param name="authenticator">Delegate used to provide information used during authentication.</param>
870 <param name="authenticationRequiredHandler">Delegate used to determine if authentication is required (may be null).</param>
871 </member> 375 </member>
872 <member name="M:HttpServer.Authentication.AuthenticationModule.#ctor(HttpServer.Authentication.AuthenticationHandler)"> 376 <member name="M:HttpServer.HttpModules.ResourceFileModule.#ctor(HttpServer.ILogWriter)">
873 <summary> 377 <summary>
874 Initializes a new instance of the <see cref="T:HttpServer.Authentication.AuthenticationModule"/> class. 378 Initializes a new instance of the <see cref="T:HttpServer.HttpModules.ResourceFileModule"/> class.
379 Runs <see cref="M:HttpServer.HttpModules.ResourceFileModule.AddDefaultMimeTypes"/> to make sure the basic mime types are available, they can be cleared later
380 through the use of <see cref="P:HttpServer.HttpModules.ResourceFileModule.MimeTypes"/> if desired.
875 </summary> 381 </summary>
876 <param name="authenticator">Delegate used to provide information used during authentication.</param> 382 <param name="logWriter">The log writer to use when logging events</param>
877 </member> 383 </member>
878 <member name="M:HttpServer.Authentication.AuthenticationModule.CreateResponse(System.String,System.Object[])"> 384 <member name="M:HttpServer.HttpModules.ResourceFileModule.AddDefaultMimeTypes">
879 <summary> 385 <summary>
880 Create a response that can be sent in the WWW-Authenticate header. 386 Mimtypes that this class can handle per default
881 </summary> 387 </summary>
882 <param name="realm">Realm that the user should authenticate in</param>
883 <param name="options">Array with optional options.</param>
884 <returns>A correct authentication request.</returns>
885 <exception cref="T:System.ArgumentNullException">If realm is empty or null.</exception>
886 </member> 388 </member>
887 <member name="M:HttpServer.Authentication.AuthenticationModule.Authenticate(System.String,System.String,System.String,System.Object[])"> 389 <member name="M:HttpServer.HttpModules.ResourceFileModule.AddResources(System.String,System.Reflection.Assembly,System.String)">
888 <summary> 390 <summary>
889 An authentication response have been received from the web browser. 391 Loads resources from a namespace in the given assembly to an uri
890 Check if it's correct
891 </summary> 392 </summary>
892 <param name="authenticationHeader">Contents from the Authorization header</param> 393 <param name="toUri">The uri to map the resources to</param>
893 <param name="realm">Realm that should be authenticated</param> 394 <param name="fromAssembly">The assembly in which the resources reside</param>
894 <param name="httpVerb">GET/POST/PUT/DELETE etc.</param> 395 <param name="fromNamespace">The namespace from which to load the resources</param>
895 <param name="options">options to specific implementations</param> 396 <usage>
896 <returns>Authentication object that is stored for the request. A user class or something like that.</returns> 397 resourceLoader.LoadResources("/user/", typeof(User).Assembly, "MyLib.Models.User.Views");
897 <exception cref="T:System.ArgumentException">if <paramref name="authenticationHeader"/> is invalid</exception> 398
898 <exception cref="T:System.ArgumentNullException">If any of the parameters is empty or null.</exception> 399 will make ie the resource MyLib.Models.User.Views.stylesheet.css accessible via /user/stylesheet.css
400 </usage>
401 <returns>The amount of loaded files, giving you the possibility of making sure the resources needed gets loaded</returns>
899 </member> 402 </member>
900 <member name="M:HttpServer.Authentication.AuthenticationModule.CheckAuthentication(System.String,System.String,System.String@,System.Object@)"> 403 <member name="M:HttpServer.HttpModules.ResourceFileModule.CanHandle(HttpServer.IHttpRequest)">
901 <summary> 404 <summary>
902 Used to invoke the authentication delegate that is used to lookup the user name/realm. 405 Returns true if the module can handle the request
903 </summary> 406 </summary>
904 <param name="realm">Realm (domain) that user want to authenticate in</param>
905 <param name="userName">User name</param>
906 <param name="password">Password used for validation. Some implementations got password in clear text, they are then sent to client.</param>
907 <param name="login">object that will be stored in the request to help you identify the user if authentication was successful.</param>
908 <returns>true if authentication was successful</returns>
909 </member> 407 </member>
910 <member name="M:HttpServer.Authentication.AuthenticationModule.AuthenticationRequired(HttpServer.IHttpRequest)"> 408 <member name="M:HttpServer.HttpModules.ResourceFileModule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)">
911 <summary> 409 <summary>
912 Determines if authentication is required. 410 Method that process the url
913 </summary> 411 </summary>
914 <param name="request">HTTP request from browser</param> 412 <param name="request">Information sent by the browser about the request</param>
915 <returns>true if user should be authenticated.</returns> 413 <param name="response">Information that is being sent back to the client.</param>
916 <remarks>throw <see cref="T:HttpServer.Exceptions.ForbiddenException"/> from your delegate if no more attempts are allowed.</remarks> 414 <param name="session">Session used to </param>
917 <exception cref="T:HttpServer.Exceptions.ForbiddenException">If no more attempts are allowed</exception> 415 <returns>true if this module handled the request.</returns>
918 </member> 416 </member>
919 <member name="P:HttpServer.Authentication.AuthenticationModule.Name"> 417 <member name="P:HttpServer.HttpModules.ResourceFileModule.MimeTypes">
920 <summary> 418 <summary>
921 name used in HTTP request. 419 List with all mime-type that are allowed.
922 </summary> 420 </summary>
421 <remarks>All other mime types will result in a Forbidden http status code.</remarks>
923 </member> 422 </member>
924 <member name="T:HttpServer.HttpInput"> 423 <member name="T:HttpServer.HttpInput">
925 <summary> 424 <summary>
@@ -1062,444 +561,216 @@
1062 <param name="name"></param> 561 <param name="name"></param>
1063 <returns>Returns <see cref="F:HttpServer.HttpInputItem.Empty"/> if item was not found.</returns> 562 <returns>Returns <see cref="F:HttpServer.HttpInputItem.Empty"/> if item was not found.</returns>
1064 </member> 563 </member>
1065 <member name="T:HttpServer.Check"> 564 <member name="T:HttpServer.Exceptions.ForbiddenException">
1066 <summary>
1067 Small design by contract implementation.
1068 </summary>
1069 </member>
1070 <member name="M:HttpServer.Check.NotEmpty(System.String,System.String)">
1071 <summary>
1072 Check whether a parameter is empty.
1073 </summary>
1074 <param name="value">Parameter value</param>
1075 <param name="parameterOrErrorMessage">Parameter name, or error description.</param>
1076 <exception cref="T:System.ArgumentException">value is empty.</exception>
1077 </member>
1078 <member name="M:HttpServer.Check.Require(System.Object,System.String)">
1079 <summary>
1080 Checks whether a parameter is null.
1081 </summary>
1082 <param name="value">Parameter value</param>
1083 <param name="parameterOrErrorMessage">Parameter name, or error description.</param>
1084 <exception cref="T:System.ArgumentNullException">value is null.</exception>
1085 </member>
1086 <member name="M:HttpServer.Check.Min(System.Int32,System.Object,System.String)">
1087 <summary>
1088 Checks whether a parameter is null.
1089 </summary>
1090 <param name="minValue"></param>
1091 <param name="value">Parameter value</param>
1092 <param name="parameterOrErrorMessage">Parameter name, or error description.</param>
1093 <exception cref="T:System.ArgumentException">value is null.</exception>
1094 </member>
1095 <member name="T:HttpServer.Method">
1096 <summary>
1097 Contains all HTTP Methods (according to the HTTP 1.1 specification)
1098 <para>
1099 See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
1100 </para>
1101 </summary>
1102 </member>
1103 <member name="F:HttpServer.Method.Delete">
1104 <summary>
1105 The DELETE method requests that the origin server delete the resource identified by the Request-URI.
1106 </summary>
1107 <remarks>
1108 <para>
1109 This method MAY be overridden by human intervention (or other means) on the origin server.
1110 The client cannot be guaranteed that the operation has been carried out, even if the status code
1111 returned from the origin server indicates that the action has been completed successfully.
1112 </para>
1113 <para>
1114 However, the server SHOULD NOT indicate success unless, at the time the response is given,
1115 it intends to delete the resource or move it to an inaccessible location.
1116 </para>
1117 <para>
1118 A successful response SHOULD be 200 (OK) if the response includes an entity describing the status,
1119 202 (Accepted) if the action has not yet been enacted,
1120 or 204 (No Content) if the action has been enacted but the response does not include an entity.
1121 </para>
1122 <para>
1123 If the request passes through a cache and the Request-URI identifies one or more currently cached entities,
1124 those entries SHOULD be treated as stale. Responses to this method are not cacheable.
1125 </para>
1126 </remarks>
1127 </member>
1128 <member name="F:HttpServer.Method.Get">
1129 <summary>
1130 The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.
1131 </summary>
1132 <remarks>
1133 <para>
1134 If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the
1135 entity in the response and not the source text of the process, unless that text happens to be the output of the process.
1136 </para>
1137 <para>
1138 The semantics of the GET method change to a "conditional GET" if the request message includes an
1139 If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field.
1140 A conditional GET method requests that the entity be transferred only under the circumstances described
1141 by the conditional header field(s). The conditional GET method is intended to reduce unnecessary network
1142 usage by allowing cached entities to be refreshed without requiring multiple requests or transferring
1143 data already held by the client.
1144 </para>
1145 </remarks>
1146 </member>
1147 <member name="F:HttpServer.Method.Header">
1148 <summary> 565 <summary>
1149 The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. 566 The server understood the request, but is refusing to fulfill it.
1150 </summary> 567 Authorization will not help and the request SHOULD NOT be repeated.
1151 <remarks> 568 If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled,
1152 The meta information contained in the HTTP headers in response to a HEAD request SHOULD be identical to the 569 it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information
1153 information sent in response to a GET request. This method can be used for obtaining meta information about 570 available to the client, the status code 404 (Not Found) can be used instead.
1154 the entity implied by the request without transferring the entity-body itself.
1155 571
1156 This method is often used for testing hypertext links for validity, accessibility, and recent modification. 572 Text taken from: http://www.submissionchamber.com/help-guides/error-codes.php
1157 </remarks>
1158 </member>
1159 <member name="F:HttpServer.Method.Options">
1160 <summary>
1161 <para>The OPTIONS method represents a request for information about the communication options available on the request/response chain identified by the Request-URI.</para>
1162 </summary> 573 </summary>
1163 <remarks>
1164 <para>This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.</para>
1165 </remarks>
1166 </member> 574 </member>
1167 <member name="F:HttpServer.Method.Post"> 575 <member name="T:HttpServer.Exceptions.HttpException">
1168 <summary> 576 <summary>
1169 The POST method is used to request that the origin server accept the entity enclosed 577 All HTTP based exceptions will derive this class.
1170 in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.
1171 </summary> 578 </summary>
1172 <remarks>
1173 POST is designed to allow a uniform method to cover the following functions:
1174 <list type="bullet">
1175 <item>
1176 Annotation of existing resources;
1177 </item><item>
1178 Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
1179 </item><item>
1180 Providing a block of data, such as the result of submitting a form, to a data-handling process;
1181 </item><item>
1182 Extending a database through an append operation.
1183 </item>
1184 </list>
1185 <para>
1186 If a resource has been created on the origin server, the response SHOULD be 201 (Created) and
1187 contain an entity which describes the status of the request and refers to the new resource, and a
1188 Location header (see section 14.30).
1189 </para>
1190 <para>
1191 The action performed by the POST method might not result in a resource that can be identified by a URI.
1192 In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on
1193 whether or not the response includes an entity that describes the result.
1194 </para><para>
1195 Responses to this method are not cacheable, unless the response includes appropriate Cache-Control
1196 or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent
1197 to retrieve a cacheable resource.
1198 </para>
1199 </remarks>
1200 </member> 579 </member>
1201 <member name="F:HttpServer.Method.Put"> 580 <member name="M:HttpServer.Exceptions.HttpException.#ctor(System.Net.HttpStatusCode,System.String)">
1202 <summary> 581 <summary>
1203 The PUT method requests that the enclosed entity be stored under the supplied Request-URI. 582 Create a new HttpException
1204 </summary> 583 </summary>
1205 <remarks> 584 <param name="code">http status code (sent in the response)</param>
1206 <list type="bullet"> 585 <param name="message">error description</param>
1207 <item>
1208 If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a
1209 modified version of the one residing on the origin server.
1210 </item><item>
1211 If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new
1212 resource by the requesting user agent, the origin server can create the resource with that URI.
1213 </item><item>
1214 If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response.
1215 </item><item>
1216 If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to
1217 indicate successful completion of the request.
1218 </item><item>
1219 If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be
1220 given that reflects the nature of the problem.
1221 </item>
1222 </list>
1223 <para>
1224 The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not
1225 understand or implement and MUST return a 501 (Not Implemented) response in such cases.
1226 </para>
1227 </remarks>
1228 </member> 586 </member>
1229 <member name="F:HttpServer.Method.Trace"> 587 <member name="M:HttpServer.Exceptions.HttpException.#ctor(System.Net.HttpStatusCode,System.String,System.Exception)">
1230 <summary> 588 <summary>
1231 The TRACE method is used to invoke a remote, application-layer loop- back of the request message. 589 Create a new HttpException
1232 </summary> 590 </summary>
591 <param name="code">http status code (sent in the response)</param>
592 <param name="message">error description</param>
593 <param name="inner">inner exception</param>
1233 </member> 594 </member>
1234 <member name="T:HttpServer.Methods"> 595 <member name="P:HttpServer.Exceptions.HttpException.HttpStatusCode">
1235 <summary> 596 <summary>
1236 Contains all HTTP Methods (according to the HTTP 1.1 specification) 597 status code to use in the response.
1237 <para>
1238 See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
1239 </para>
1240 </summary> 598 </summary>
1241 </member> 599 </member>
1242 <member name="F:HttpServer.Methods.Delete"> 600 <member name="M:HttpServer.Exceptions.ForbiddenException.#ctor(System.String)">
1243 <summary> 601 <summary>
1244 The DELETE method requests that the origin server delete the resource identified by the Request-URI. 602 Initializes a new instance of the <see cref="T:HttpServer.Exceptions.ForbiddenException"/> class.
1245 </summary> 603 </summary>
1246 <remarks> 604 <param name="errorMsg">error message</param>
1247 <para>
1248 This method MAY be overridden by human intervention (or other means) on the origin server.
1249 The client cannot be guaranteed that the operation has been carried out, even if the status code
1250 returned from the origin server indicates that the action has been completed successfully.
1251 </para>
1252 <para>
1253 However, the server SHOULD NOT indicate success unless, at the time the response is given,
1254 it intends to delete the resource or move it to an inaccessible location.
1255 </para>
1256 <para>
1257 A successful response SHOULD be 200 (OK) if the response includes an entity describing the status,
1258 202 (Accepted) if the action has not yet been enacted,
1259 or 204 (No Content) if the action has been enacted but the response does not include an entity.
1260 </para>
1261 <para>
1262 If the request passes through a cache and the Request-URI identifies one or more currently cached entities,
1263 those entries SHOULD be treated as stale. Responses to this method are not cacheable.
1264 </para>
1265 </remarks>
1266 </member> 605 </member>
1267 <member name="F:HttpServer.Methods.Get"> 606 <member name="T:HttpServer.RequestCookies">
1268 <summary> 607 <summary>
1269 The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. 608 This class is created as a wrapper, since there are two different cookie types in .Net (Cookie and HttpCookie).
609 The framework might switch class in the future and we dont want to have to replace all instances
1270 </summary> 610 </summary>
1271 <remarks>
1272 <para>
1273 If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the
1274 entity in the response and not the source text of the process, unless that text happens to be the output of the process.
1275 </para>
1276 <para>
1277 The semantics of the GET method change to a "conditional GET" if the request message includes an
1278 If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field.
1279 A conditional GET method requests that the entity be transferred only under the circumstances described
1280 by the conditional header field(s). The conditional GET method is intended to reduce unnecessary network
1281 usage by allowing cached entities to be refreshed without requiring multiple requests or transferring
1282 data already held by the client.
1283 </para>
1284 </remarks>
1285 </member> 611 </member>
1286 <member name="F:HttpServer.Methods.Header"> 612 <member name="M:HttpServer.RequestCookies.#ctor(System.String)">
1287 <summary> 613 <summary>
1288 The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. 614 Let's copy all the cookies.
1289 </summary> 615 </summary>
1290 <remarks> 616 <param name="cookies">value from cookie header.</param>
1291 The meta information contained in the HTTP headers in response to a HEAD request SHOULD be identical to the
1292 information sent in response to a GET request. This method can be used for obtaining meta information about
1293 the entity implied by the request without transferring the entity-body itself.
1294
1295 This method is often used for testing hypertext links for validity, accessibility, and recent modification.
1296 </remarks>
1297 </member> 617 </member>
1298 <member name="F:HttpServer.Methods.Options"> 618 <member name="M:HttpServer.RequestCookies.Add(HttpServer.RequestCookie)">
1299 <summary> 619 <summary>
1300 <para>The OPTIONS method represents a request for information about the communication options available on the request/response chain identified by the Request-URI.</para> 620 Adds a cookie in the collection.
1301 </summary> 621 </summary>
1302 <remarks> 622 <param name="cookie">cookie to add</param>
1303 <para>This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.</para> 623 <exception cref="T:System.ArgumentNullException">cookie is null</exception>
1304 </remarks>
1305 </member> 624 </member>
1306 <member name="F:HttpServer.Methods.Post"> 625 <member name="M:HttpServer.RequestCookies.GetEnumerator">
1307 <summary> 626 <summary>
1308 The POST method is used to request that the origin server accept the entity enclosed 627 Gets a collection enumerator on the cookie list.
1309 in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.
1310 </summary> 628 </summary>
1311 <remarks> 629 <returns>collection enumerator</returns>
1312 POST is designed to allow a uniform method to cover the following functions:
1313 <list type="bullet">
1314 <item>
1315 Annotation of existing resources;
1316 </item><item>
1317 Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
1318 </item><item>
1319 Providing a block of data, such as the result of submitting a form, to a data-handling process;
1320 </item><item>
1321 Extending a database through an append operation.
1322 </item>
1323 </list>
1324 <para>
1325 If a resource has been created on the origin server, the response SHOULD be 201 (Created) and
1326 contain an entity which describes the status of the request and refers to the new resource, and a
1327 Location header (see section 14.30).
1328 </para>
1329 <para>
1330 The action performed by the POST method might not result in a resource that can be identified by a URI.
1331 In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on
1332 whether or not the response includes an entity that describes the result.
1333 </para><para>
1334 Responses to this method are not cacheable, unless the response includes appropriate Cache-Control
1335 or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent
1336 to retrieve a cacheable resource.
1337 </para>
1338 </remarks>
1339 </member> 630 </member>
1340 <member name="F:HttpServer.Methods.Put"> 631 <member name="M:HttpServer.RequestCookies.Clear">
1341 <summary> 632 <summary>
1342 The PUT method requests that the enclosed entity be stored under the supplied Request-URI. 633 Remove all cookies.
1343 </summary> 634 </summary>
1344 <remarks>
1345 <list type="bullet">
1346 <item>
1347 If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a
1348 modified version of the one residing on the origin server.
1349 </item><item>
1350 If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new
1351 resource by the requesting user agent, the origin server can create the resource with that URI.
1352 </item><item>
1353 If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response.
1354 </item><item>
1355 If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to
1356 indicate successful completion of the request.
1357 </item><item>
1358 If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be
1359 given that reflects the nature of the problem.
1360 </item>
1361 </list>
1362 <para>
1363 The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not
1364 understand or implement and MUST return a 501 (Not Implemented) response in such cases.
1365 </para>
1366 </remarks>
1367 </member> 635 </member>
1368 <member name="F:HttpServer.Methods.Trace"> 636 <member name="M:HttpServer.RequestCookies.System#Collections#Generic#IEnumerable{HttpServer#RequestCookie}#GetEnumerator">
1369 <summary> 637 <summary>
1370 The TRACE method is used to invoke a remote, application-layer loop- back of the request message. 638 Returns an enumerator that iterates through the collection.
1371 </summary> 639 </summary>
640
641 <returns>
642 A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> that can be used to iterate through the collection.
643 </returns>
644 <filterpriority>1</filterpriority>
1372 </member> 645 </member>
1373 <member name="T:HttpServer.LogPrio"> 646 <member name="M:HttpServer.RequestCookies.Remove(System.String)">
1374 <summary> 647 <summary>
1375 Priority for log entries 648 Remove a cookie from the collection.
1376 </summary> 649 </summary>
1377 <seealso cref="T:HttpServer.ILogWriter"/> 650 <param name="cookieName">Name of cookie.</param>
1378 </member> 651 </member>
1379 <member name="F:HttpServer.LogPrio.Trace"> 652 <member name="P:HttpServer.RequestCookies.Count">
1380 <summary> 653 <summary>
1381 Very detailed logs to be able to follow the flow of the program. 654 Gets the count of cookies in the collection.
1382 </summary> 655 </summary>
1383 </member> 656 </member>
1384 <member name="F:HttpServer.LogPrio.Debug"> 657 <member name="P:HttpServer.RequestCookies.Item(System.String)">
1385 <summary> 658 <summary>
1386 Logs to help debug errors in the application 659 Gets the cookie of a given identifier (null if not existing).
1387 </summary> 660 </summary>
1388 </member> 661 </member>
1389 <member name="F:HttpServer.LogPrio.Info"> 662 <member name="T:HttpServer.IHttpClientContext">
1390 <summary> 663 <summary>
1391 Information to be able to keep track of state changes etc. 664 Contains a connection to a browser/client.
1392 </summary> 665 </summary>
1393 </member> 666 </member>
1394 <member name="F:HttpServer.LogPrio.Warning"> 667 <member name="M:HttpServer.IHttpClientContext.Disconnect(System.Net.Sockets.SocketError)">
1395 <summary> 668 <summary>
1396 Something did not go as we expected, but it's no problem. 669 Disconnect from client
1397 </summary> 670 </summary>
671 <param name="error">error to report in the <see cref="E:HttpServer.IHttpClientContext.Disconnected"/> event.</param>
1398 </member> 672 </member>
1399 <member name="F:HttpServer.LogPrio.Error"> 673 <member name="M:HttpServer.IHttpClientContext.Respond(System.String,System.Net.HttpStatusCode,System.String,System.String,System.String)">
1400 <summary> 674 <summary>
1401 Something that should not fail failed, but we can still keep 675 Send a response.
1402 on going.
1403 </summary> 676 </summary>
677 <param name="httpVersion">Either <see cref="F:HttpServer.HttpHelper.HTTP10"/> or <see cref="F:HttpServer.HttpHelper.HTTP11"/></param>
678 <param name="statusCode">HTTP status code</param>
679 <param name="reason">reason for the status code.</param>
680 <param name="body">HTML body contents, can be null or empty.</param>
681 <param name="contentType">A content type to return the body as, i.e. 'text/html' or 'text/plain', defaults to 'text/html' if null or empty</param>
682 <exception cref="T:System.ArgumentException">If <paramref name="httpVersion"/> is invalid.</exception>
1404 </member> 683 </member>
1405 <member name="F:HttpServer.LogPrio.Fatal"> 684 <member name="M:HttpServer.IHttpClientContext.Respond(System.String,System.Net.HttpStatusCode,System.String)">
1406 <summary> 685 <summary>
1407 Something failed, and we cannot handle it properly. 686 Send a response.
1408 </summary> 687 </summary>
688 <param name="httpVersion">Either <see cref="F:HttpServer.HttpHelper.HTTP10"/> or <see cref="F:HttpServer.HttpHelper.HTTP11"/></param>
689 <param name="statusCode">HTTP status code</param>
690 <param name="reason">reason for the status code.</param>
1409 </member> 691 </member>
1410 <member name="T:HttpServer.ILogWriter"> 692 <member name="M:HttpServer.IHttpClientContext.Respond(System.String)">
1411 <summary> 693 <summary>
1412 Interface used to write to log files. 694 Send a response.
1413 </summary> 695 </summary>
696 <exception cref="T:System.ArgumentNullException"></exception>
1414 </member> 697 </member>
1415 <member name="M:HttpServer.ILogWriter.Write(System.Object,HttpServer.LogPrio,System.String)"> 698 <member name="M:HttpServer.IHttpClientContext.Send(System.Byte[])">
1416 <summary> 699 <summary>
1417 Write an entry to the log file. 700 send a whole buffer
1418 </summary> 701 </summary>
1419 <param name="source">object that is writing to the log</param> 702 <param name="buffer">buffer to send</param>
1420 <param name="priority">importance of the log message</param> 703 <exception cref="T:System.ArgumentNullException"></exception>
1421 <param name="message">the message</param>
1422 </member> 704 </member>
1423 <member name="T:HttpServer.ConsoleLogWriter"> 705 <member name="M:HttpServer.IHttpClientContext.Send(System.Byte[],System.Int32,System.Int32)">
1424 <summary> 706 <summary>
1425 This class writes to the console. It colors the output depending on the logprio and includes a 3-level stacktrace (in debug mode) 707 Send data using the stream
1426 </summary> 708 </summary>
1427 <seealso cref="T:HttpServer.ILogWriter"/> 709 <param name="buffer">Contains data to send</param>
710 <param name="offset">Start position in buffer</param>
711 <param name="size">number of bytes to send</param>
712 <exception cref="T:System.ArgumentNullException"></exception>
713 <exception cref="T:System.ArgumentOutOfRangeException"></exception>
1428 </member> 714 </member>
1429 <member name="F:HttpServer.ConsoleLogWriter.Instance"> 715 <member name="M:HttpServer.IHttpClientContext.Close">
1430 <summary> 716 <summary>
1431 The actual instance of this class. 717 Closes the streams and disposes of the unmanaged resources
1432 </summary> 718 </summary>
1433 </member> 719 </member>
1434 <member name="M:HttpServer.ConsoleLogWriter.Write(System.Object,HttpServer.LogPrio,System.String)"> 720 <member name="P:HttpServer.IHttpClientContext.Secured">
1435 <summary> 721 <summary>
1436 Logwriters the specified source. 722 Using SSL or other encryption method.
1437 </summary> 723 </summary>
1438 <param name="source">object that wrote the logentry.</param>
1439 <param name="prio">Importance of the log message</param>
1440 <param name="message">The message.</param>
1441 </member> 724 </member>
1442 <member name="M:HttpServer.ConsoleLogWriter.GetColor(HttpServer.LogPrio)"> 725 <member name="P:HttpServer.IHttpClientContext.IsSecured">
1443 <summary> 726 <summary>
1444 Get color for the specified logprio 727 Using SSL or other encryption method.
1445 </summary> 728 </summary>
1446 <param name="prio">prio for the log entry</param>
1447 <returns>A <see cref="T:System.ConsoleColor"/> for the prio</returns>
1448 </member> 729 </member>
1449 <member name="T:HttpServer.NullLogWriter"> 730 <member name="E:HttpServer.IHttpClientContext.Disconnected">
1450 <summary> 731 <summary>
1451 Default log writer, writes everything to null (nowhere). 732 The context have been disconnected.
1452 </summary> 733 </summary>
1453 <seealso cref="T:HttpServer.ILogWriter"/> 734 <remarks>
735 Event can be used to clean up a context, or to reuse it.
736 </remarks>
1454 </member> 737 </member>
1455 <member name="F:HttpServer.NullLogWriter.Instance"> 738 <member name="E:HttpServer.IHttpClientContext.RequestReceived">
1456 <summary> 739 <summary>
1457 The logging instance. 740 A request have been received in the context.
1458 </summary> 741 </summary>
1459 </member> 742 </member>
1460 <member name="M:HttpServer.NullLogWriter.Write(System.Object,HttpServer.LogPrio,System.String)"> 743 <member name="T:HttpServer.DisconnectedEventArgs">
1461 <summary> 744 <summary>
1462 Writes everything to null 745 A <see cref="T:HttpServer.IHttpClientContext"/> have been disconnected.
1463 </summary> 746 </summary>
1464 <param name="source">object that wrote the log entry.</param>
1465 <param name="prio">Importance of the log message</param>
1466 <param name="message">The message.</param>
1467 </member> 747 </member>
1468 <member name="T:HttpServer.IComponentProvider"> 748 <member name="M:HttpServer.DisconnectedEventArgs.#ctor(System.Net.Sockets.SocketError)">
1469 <summary> 749 <summary>
1470 Inversion of control interface. 750 Initializes a new instance of the <see cref="T:HttpServer.DisconnectedEventArgs"/> class.
1471 </summary> 751 </summary>
752 <param name="error">Reason to disconnection.</param>
1472 </member> 753 </member>
1473 <member name="M:HttpServer.IComponentProvider.AddInstance``1(System.Object)"> 754 <member name="P:HttpServer.DisconnectedEventArgs.Error">
1474 <summary> 755 <summary>
1475 Add a component instance 756 Gets reason to why client disconnected.
1476 </summary> 757 </summary>
1477 <typeparam name="T">Interface type</typeparam>
1478 <param name="instance">Instance to add</param>
1479 </member> 758 </member>
1480 <member name="M:HttpServer.IComponentProvider.Get``1"> 759 <member name="T:HttpServer.RequestEventArgs">
1481 <summary> 760 <summary>
1482 Get a component. 761
1483 </summary> 762 </summary>
1484 <typeparam name="T">Interface type</typeparam>
1485 <returns>Component if registered, otherwise null.</returns>
1486 <remarks>
1487 Component will get created if needed.
1488 </remarks>
1489 </member> 763 </member>
1490 <member name="M:HttpServer.IComponentProvider.Contains(System.Type)"> 764 <member name="M:HttpServer.RequestEventArgs.#ctor(HttpServer.IHttpRequest)">
1491 <summary> 765 <summary>
1492 Checks if the specified component interface have been added. 766 Initializes a new instance of the <see cref="T:HttpServer.RequestEventArgs"/> class.
1493 </summary> 767 </summary>
1494 <param name="interfaceType"></param> 768 <param name="request">The request.</param>
1495 <returns>true if found; otherwise false.</returns>
1496 </member> 769 </member>
1497 <member name="M:HttpServer.IComponentProvider.Add``2"> 770 <member name="P:HttpServer.RequestEventArgs.Request">
1498 <summary> 771 <summary>
1499 Add a component. 772 Gets received request.
1500 </summary> 773 </summary>
1501 <typeparam name="InterfaceType">Type being requested.</typeparam>
1502 <typeparam name="InstanceType">Type being created.</typeparam>
1503 </member> 774 </member>
1504 <member name="T:HttpServer.HttpParam"> 775 <member name="T:HttpServer.HttpParam">
1505 <summary> 776 <summary>
@@ -1555,55 +826,125 @@
1555 <param name="name"></param> 826 <param name="name"></param>
1556 <returns>Item if found; otherwise HttpInputItem.EmptyLanguageNode</returns> 827 <returns>Item if found; otherwise HttpInputItem.EmptyLanguageNode</returns>
1557 </member> 828 </member>
1558 <member name="T:HttpServer.HttpForm"> 829 <member name="T:HttpServer.HttpFile">
1559 <summary>Container for posted form data</summary> 830 <summary>
831 Container class for posted files
832 </summary>
1560 </member> 833 </member>
1561 <member name="F:HttpServer.HttpForm.EmptyForm"> 834 <member name="M:HttpServer.HttpFile.#ctor(System.String,System.String,System.String,System.String)">
1562 <summary>Instance to help mark a non-initialized form</summary> 835 <summary>
836 Creates a container for a posted file
837 </summary>
838 <param name="name">The identifier of the post field</param>
839 <param name="filename">The file path</param>
840 <param name="contentType">The content type of the file</param>
841 <param name="uploadFilename">The name of the file uploaded</param>
842 <exception cref="T:System.ArgumentNullException">If any parameter is null or empty</exception>
1563 </member> 843 </member>
1564 <member name="M:HttpServer.HttpForm.#ctor"> 844 <member name="M:HttpServer.HttpFile.#ctor(System.String,System.String,System.String)">
1565 <summary>Initializes a form container with the specified name</summary> 845 <summary>
846 Creates a container for a posted file <see cref="M:HttpServer.HttpFile.#ctor(System.String,System.String,System.String,System.String)"/>
847 </summary>
848 <exception cref="T:System.ArgumentNullException">If any parameter is null or empty</exception>
1566 </member> 849 </member>
1567 <member name="M:HttpServer.HttpForm.#ctor(HttpServer.HttpInput)"> 850 <member name="M:HttpServer.HttpFile.Finalize">
851 <summary>Destructor disposing the file</summary>
852 </member>
853 <member name="M:HttpServer.HttpFile.Dispose(System.Boolean)">
1568 <summary> 854 <summary>
1569 Makes a deep copy of the input 855 Deletes the temporary file
1570 </summary> 856 </summary>
1571 <param name="input">The input to copy</param> 857 <param name="disposing">True if manual dispose</param>
1572 </member> 858 </member>
1573 <member name="M:HttpServer.HttpForm.AddFile(HttpServer.HttpFile)"> 859 <member name="M:HttpServer.HttpFile.Dispose">
1574 <summary> 860 <summary>
1575 Adds a file to the collection of posted files 861 Disposing interface, cleans up managed resources (the temporary file) and suppresses finalization
1576 </summary> 862 </summary>
1577 <param name="file">The file to add</param>
1578 <exception cref="T:System.ArgumentException">If the file is already added</exception>
1579 <exception cref="T:System.ArgumentNullException">If file is null</exception>
1580 <exception cref="T:System.InvalidOperationException">If the instance is HttpForm.EmptyForm which cannot be modified</exception>
1581 </member> 863 </member>
1582 <member name="M:HttpServer.HttpForm.ContainsFile(System.String)"> 864 <member name="P:HttpServer.HttpFile.Name">
1583 <summary> 865 <summary>
1584 Checks if the form contains a specified file 866 The name/id of the file
1585 </summary> 867 </summary>
1586 <param name="name">Field name of the file parameter</param>
1587 <returns>True if the file exists</returns>
1588 <exception cref="T:System.InvalidOperationException">If the instance is HttpForm.EmptyForm which cannot be modified</exception>
1589 </member> 868 </member>
1590 <member name="M:HttpServer.HttpForm.GetFile(System.String)"> 869 <member name="P:HttpServer.HttpFile.Filename">
1591 <summary> 870 <summary>
1592 Retrieves a file held by by the form 871 The full file path
1593 </summary> 872 </summary>
1594 <param name="name">The identifier of the file</param>
1595 <returns>The requested file or null if the file was not found</returns>
1596 <exception cref="T:System.ArgumentNullException">If name is null or empty</exception>
1597 <exception cref="T:System.InvalidOperationException">If the instance is HttpForm.EmptyForm which cannot be modified</exception>
1598 </member> 873 </member>
1599 <member name="M:HttpServer.HttpForm.Clear"> 874 <member name="P:HttpServer.HttpFile.UploadFilename">
1600 <summary>Disposes all held HttpFile's and resets values</summary> 875 <summary>
876 The name of the uploaded file
877 </summary>
1601 </member> 878 </member>
1602 <member name="P:HttpServer.HttpForm.Files"> 879 <member name="P:HttpServer.HttpFile.ContentType">
1603 <summary> 880 <summary>
1604 Retrieves the number of files added to the <see cref="T:HttpServer.HttpForm"/> 881 The type of file
1605 </summary> 882 </summary>
1606 <returns>0 if no files are added</returns> 883 </member>
884 <member name="T:HttpServer.FormDecoders.XmlDecoder">
885 <summary>
886 This decoder converts XML documents to form items.
887 Each element becomes a subitem in the form, and each attribute becomes an item.
888 </summary>
889 <example>
890 // xml: <hello id="1">something<world id="2">data</world></hello>
891 // result:
892 // form["hello"].Value = "something"
893 // form["hello"]["id"].Value = 1
894 // form["hello"]["world]["id"].Value = 1
895 // form["hello"]["world"].Value = "data"
896 </example>
897 <remarks>
898 The original xml document is stored in form["__xml__"].Value.
899 </remarks>
900 </member>
901 <member name="T:HttpServer.FormDecoders.IFormDecoder">
902 <summary>
903 Interface for form content decoders.
904 </summary>
905 </member>
906 <member name="M:HttpServer.FormDecoders.IFormDecoder.Decode(System.IO.Stream,System.String,System.Text.Encoding)">
907 <summary>
908
909 </summary>
910 <param name="stream">Stream containing the content</param>
911 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case</param>
912 <param name="encoding">Stream enconding</param>
913 <returns>A http form, or null if content could not be parsed.</returns>
914 <exception cref="T:System.IO.InvalidDataException">If contents in the stream is not valid input data.</exception>
915 </member>
916 <member name="M:HttpServer.FormDecoders.IFormDecoder.CanParse(System.String)">
917 <summary>
918 Checks if the decoder can handle the mime type
919 </summary>
920 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case.</param>
921 <returns>True if the decoder can parse the specified content type</returns>
922 </member>
923 <member name="M:HttpServer.FormDecoders.XmlDecoder.Decode(System.IO.Stream,System.String,System.Text.Encoding)">
924 <summary>
925
926 </summary>
927 <param name="stream">Stream containing the content</param>
928 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case</param>
929 <param name="encoding">Stream encoding</param>
930 Note: contentType and encoding are not used?
931 <returns>A http form, or null if content could not be parsed.</returns>
932 <exception cref="T:System.IO.InvalidDataException"></exception>
933 </member>
934 <member name="M:HttpServer.FormDecoders.XmlDecoder.TraverseNode(HttpServer.IHttpInput,System.Xml.XmlNode)">
935 <summary>
936 Recursive function that will go through an xml element and store it's content
937 to the form item.
938 </summary>
939 <param name="item">(parent) Item in form that content should be added to.</param>
940 <param name="node">Node that should be parsed.</param>
941 </member>
942 <member name="M:HttpServer.FormDecoders.XmlDecoder.CanParse(System.String)">
943 <summary>
944 Checks if the decoder can handle the mime type
945 </summary>
946 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case.</param>
947 <returns>True if the decoder can parse the specified content type</returns>
1607 </member> 948 </member>
1608 <member name="T:HttpServer.Helpers.ObjectForm"> 949 <member name="T:HttpServer.Helpers.ObjectForm">
1609 <summary> 950 <summary>
@@ -1722,405 +1063,397 @@
1722 </summary> 1063 </summary>
1723 <returns>html</returns> 1064 <returns>html</returns>
1724 </member> 1065 </member>
1725 <member name="T:HttpServer.FormDecoders.FormDecoderProvider"> 1066 <member name="T:HttpServer.FormDecoders.MultipartDecoder">
1726 <summary>
1727 This provider is used to let us implement any type of form decoding we want without
1728 having to rewrite anything else in the server.
1729 </summary>
1730 </member>
1731 <member name="M:HttpServer.FormDecoders.FormDecoderProvider.Decode(System.String,System.IO.Stream,System.Text.Encoding)">
1732 <summary> 1067 <summary>
1733 1068
1734 </summary> 1069 </summary>
1735 <param name="contentType">Should contain boundary and type, as in: multipart/form-data; boundary=---------------------------230051238959</param> 1070 <remarks>
1736 <param name="stream">Stream containing form data.</param> 1071 http://www.faqs.org/rfcs/rfc1867.html
1737 <param name="encoding">Encoding used when decoding the stream</param> 1072 </remarks>
1738 <returns><see cref="F:HttpServer.HttpInput.Empty"/> if no parser was found.</returns>
1739 <exception cref="T:System.ArgumentException">If stream is null or not readable.</exception>
1740 <exception cref="T:System.IO.InvalidDataException">If stream contents cannot be decoded properly.</exception>
1741 </member> 1073 </member>
1742 <member name="M:HttpServer.FormDecoders.FormDecoderProvider.Add(HttpServer.FormDecoders.IFormDecoder)"> 1074 <member name="F:HttpServer.FormDecoders.MultipartDecoder.MimeType">
1743 <summary> 1075 <summary>
1744 Add a decoder. 1076 multipart/form-data
1745 </summary> 1077 </summary>
1746 <param name="decoder"></param>
1747 <exception cref="T:System.ArgumentNullException"></exception>
1748 </member> 1078 </member>
1749 <member name="P:HttpServer.FormDecoders.FormDecoderProvider.Count"> 1079 <member name="F:HttpServer.FormDecoders.MultipartDecoder.FormData">
1750 <summary> 1080 <summary>
1751 Number of added decoders. 1081 form-data
1752 </summary> 1082 </summary>
1753 </member> 1083 </member>
1754 <member name="P:HttpServer.FormDecoders.FormDecoderProvider.Decoders"> 1084 <member name="M:HttpServer.FormDecoders.MultipartDecoder.Decode(System.IO.Stream,System.String,System.Text.Encoding)">
1755 <summary> 1085 <summary>
1756 Use with care. 1086
1757 </summary> 1087 </summary>
1088 <param name="stream">Stream containing the content</param>
1089 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case</param>
1090 <param name="encoding">Stream enconding</param>
1091 <returns>A http form, or null if content could not be parsed.</returns>
1092 <exception cref="T:System.IO.InvalidDataException">If contents in the stream is not valid input data.</exception>
1093 <exception cref="T:System.ArgumentNullException">If any parameter is null</exception>
1758 </member> 1094 </member>
1759 <member name="P:HttpServer.FormDecoders.FormDecoderProvider.DefaultDecoder"> 1095 <member name="M:HttpServer.FormDecoders.MultipartDecoder.CanParse(System.String)">
1760 <summary> 1096 <summary>
1761 Decoder used for unknown content types. 1097 Checks if the decoder can handle the mime type
1762 </summary> 1098 </summary>
1099 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case.</param>
1100 <returns>True if the decoder can parse the specified content type</returns>
1763 </member> 1101 </member>
1764 <member name="T:HttpServer.ExceptionHandler"> 1102 <member name="T:HttpServer.Exceptions.BadRequestException">
1765 <summary> 1103 <summary>
1766 We dont want to let the server to die due to exceptions thrown in worker threads. 1104 The request could not be understood by the server due to malformed syntax.
1767 therefore we use this delegate to give you a change to handle uncaught exceptions. 1105 The client SHOULD NOT repeat the request without modifications.
1106
1107 Text taken from: http://www.submissionchamber.com/help-guides/error-codes.php
1768 </summary> 1108 </summary>
1769 <param name="source">Class that the exception was thrown in.</param>
1770 <param name="exception">Exception</param>
1771 <remarks>
1772 Server will throw a InternalServerException in release version if you dont
1773 handle this delegate.
1774 </remarks>
1775 </member> 1109 </member>
1776 <member name="T:HttpServer.HttpClientContext"> 1110 <member name="M:HttpServer.Exceptions.BadRequestException.#ctor(System.String)">
1777 <summary> 1111 <summary>
1778 Contains a connection to a browser/client. 1112 Create a new bad request exception.
1779 </summary> 1113 </summary>
1780 <remarks> 1114 <param name="errMsg">reason to why the request was bad.</param>
1781 Remember to <see cref="M:HttpServer.HttpClientContext.Start"/> after you have hooked the <see cref="E:HttpServer.HttpClientContext.RequestReceived"/> event.
1782 </remarks>
1783 TODO: Maybe this class should be broken up into HttpClientChannel and HttpClientContext?
1784 </member> 1115 </member>
1785 <member name="M:HttpServer.HttpClientContext.#ctor(System.Boolean,System.Net.IPEndPoint,System.IO.Stream,HttpServer.IRequestParserFactory,System.Int32,System.Net.Sockets.Socket)"> 1116 <member name="M:HttpServer.Exceptions.BadRequestException.#ctor(System.String,System.Exception)">
1786 <summary> 1117 <summary>
1787 Initializes a new instance of the <see cref="T:HttpServer.HttpClientContext"/> class. 1118 Create a new bad request exception.
1788 </summary> 1119 </summary>
1789 <param name="secured">true if the connection is secured (SSL/TLS)</param> 1120 <param name="errMsg">reason to why the request was bad.</param>
1790 <param name="remoteEndPoint">client that connected.</param> 1121 <param name="inner">inner exception</param>
1791 <param name="stream">Stream used for communication</param>
1792 <param name="parserFactory">Used to create a <see cref="T:HttpServer.IHttpRequestParser"/>.</param>
1793 <param name="bufferSize">Size of buffer to use when reading data. Must be at least 4096 bytes.</param>
1794 <exception cref="T:System.Net.Sockets.SocketException">If <see cref="M:System.Net.Sockets.Socket.BeginReceive(System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.AsyncCallback,System.Object)"/> fails</exception>
1795 <exception cref="T:System.ArgumentException">Stream must be writable and readable.</exception>
1796 </member> 1122 </member>
1797 <member name="M:HttpServer.HttpClientContext.OnBodyBytesReceived(System.Object,HttpServer.Parser.BodyEventArgs)"> 1123 <member name="T:HttpServer.ResponseCookies">
1798 <summary> 1124 <summary>
1799 Process incoming body bytes. 1125 Cookies that should be set.
1800 </summary> 1126 </summary>
1801 <param name="sender"><see cref="T:HttpServer.IHttpRequestParser"/></param>
1802 <param name="e">Bytes</param>
1803 </member> 1127 </member>
1804 <member name="M:HttpServer.HttpClientContext.OnHeaderReceived(System.Object,HttpServer.Parser.HeaderEventArgs)"> 1128 <member name="M:HttpServer.ResponseCookies.Add(HttpServer.ResponseCookie)">
1805 <summary> 1129 <summary>
1806 1130 Adds a cookie in the collection.
1807 </summary> 1131 </summary>
1808 <param name="sender"></param> 1132 <param name="cookie">cookie to add</param>
1809 <param name="e"></param> 1133 <exception cref="T:System.ArgumentNullException">cookie is null</exception>
1810 </member> 1134 </member>
1811 <member name="M:HttpServer.HttpClientContext.Start"> 1135 <member name="M:HttpServer.ResponseCookies.Add(HttpServer.RequestCookie,System.DateTime)">
1812 <summary> 1136 <summary>
1813 Start reading content. 1137 Copy a request cookie
1814 </summary> 1138 </summary>
1815 <remarks> 1139 <param name="cookie"></param>
1816 Make sure to call base.Start() if you override this method. 1140 <param name="expires">When the cookie should expire</param>
1817 </remarks>
1818 </member> 1141 </member>
1819 <member name="M:HttpServer.HttpClientContext.Cleanup"> 1142 <member name="M:HttpServer.ResponseCookies.GetEnumerator">
1820 <summary> 1143 <summary>
1821 Clean up context. 1144 Gets a collection enumerator on the cookie list.
1822 </summary> 1145 </summary>
1823 <remarks> 1146 <returns>collection enumerator</returns>
1824 Make sure to call base.Cleanup() if you override the method.
1825 </remarks>
1826 </member> 1147 </member>
1827 <member name="M:HttpServer.HttpClientContext.Disconnect(System.Net.Sockets.SocketError)"> 1148 <member name="M:HttpServer.ResponseCookies.Clear">
1828 <summary> 1149 <summary>
1829 Disconnect from client 1150 Remove all cookies
1830 </summary> 1151 </summary>
1831 <param name="error">error to report in the <see cref="E:HttpServer.HttpClientContext.Disconnected"/> event.</param>
1832 </member> 1152 </member>
1833 <member name="M:HttpServer.HttpClientContext.Respond(System.String,System.Net.HttpStatusCode,System.String,System.String,System.String)"> 1153 <member name="M:HttpServer.ResponseCookies.System#Collections#Generic#IEnumerable{HttpServer#ResponseCookie}#GetEnumerator">
1834 <summary> 1154 <summary>
1835 Send a response. 1155 Returns an enumerator that iterates through the collection.
1836 </summary> 1156 </summary>
1837 <param name="httpVersion">Either <see cref="F:HttpServer.HttpHelper.HTTP10"/> or <see cref="F:HttpServer.HttpHelper.HTTP11"/></param> 1157
1838 <param name="statusCode">HTTP status code</param> 1158 <returns>
1839 <param name="reason">reason for the status code.</param> 1159 A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> that can be used to iterate through the collection.
1840 <param name="body">HTML body contents, can be null or empty.</param> 1160 </returns>
1841 <param name="contentType">A content type to return the body as, i.e. 'text/html' or 'text/plain', defaults to 'text/html' if null or empty</param> 1161 <filterpriority>1</filterpriority>
1842 <exception cref="T:System.ArgumentException">If <paramref name="httpVersion"/> is invalid.</exception>
1843 </member> 1162 </member>
1844 <member name="M:HttpServer.HttpClientContext.Respond(System.String,System.Net.HttpStatusCode,System.String)"> 1163 <member name="P:HttpServer.ResponseCookies.Count">
1845 <summary> 1164 <summary>
1846 Send a response. 1165 Gets the count of cookies in the collection.
1847 </summary> 1166 </summary>
1848 <param name="httpVersion">Either <see cref="F:HttpServer.HttpHelper.HTTP10"/> or <see cref="F:HttpServer.HttpHelper.HTTP11"/></param>
1849 <param name="statusCode">HTTP status code</param>
1850 <param name="reason">reason for the status code.</param>
1851 </member> 1167 </member>
1852 <member name="M:HttpServer.HttpClientContext.Respond(System.String)"> 1168 <member name="P:HttpServer.ResponseCookies.Item(System.String)">
1853 <summary> 1169 <summary>
1854 Send a response. 1170 Gets the cookie of a given identifier (null if not existing).
1855 </summary> 1171 </summary>
1856 <exception cref="T:System.ArgumentNullException"></exception>
1857 </member> 1172 </member>
1858 <member name="M:HttpServer.HttpClientContext.Send(System.Byte[])"> 1173 <member name="T:HttpServer.ResponseCookie">
1859 <summary> 1174 <summary>
1860 send a whole buffer 1175 cookie being sent back to the browser.
1861 </summary> 1176 </summary>
1862 <param name="buffer">buffer to send</param> 1177 <seealso cref="T:HttpServer.ResponseCookie"/>
1863 <exception cref="T:System.ArgumentNullException"></exception>
1864 </member> 1178 </member>
1865 <member name="M:HttpServer.HttpClientContext.Send(System.Byte[],System.Int32,System.Int32)"> 1179 <member name="T:HttpServer.RequestCookie">
1866 <summary> 1180 <summary>
1867 Send data using the stream 1181 cookie sent by the client/browser
1868 </summary> 1182 </summary>
1869 <param name="buffer">Contains data to send</param> 1183 <seealso cref="T:HttpServer.ResponseCookie"/>
1870 <param name="offset">Start position in buffer</param>
1871 <param name="size">number of bytes to send</param>
1872 <exception cref="T:System.ArgumentNullException"></exception>
1873 <exception cref="T:System.ArgumentOutOfRangeException"></exception>
1874 </member> 1184 </member>
1875 <member name="E:HttpServer.HttpClientContext.Cleaned"> 1185 <member name="M:HttpServer.RequestCookie.#ctor(System.String,System.String)">
1876 <summary> 1186 <summary>
1877 This context have been cleaned, which means that it can be reused. 1187 Constructor.
1878 </summary> 1188 </summary>
1189 <param name="id">cookie identifier</param>
1190 <param name="content">cookie content</param>
1191 <exception cref="T:System.ArgumentNullException">id or content is null</exception>
1192 <exception cref="T:System.ArgumentException">id is empty</exception>
1879 </member> 1193 </member>
1880 <member name="E:HttpServer.HttpClientContext.Started"> 1194 <member name="M:HttpServer.RequestCookie.ToString">
1881 <summary> 1195 <summary>
1882 Context have been started (a new client have connected) 1196 Gets the cookie HTML representation.
1883 </summary> 1197 </summary>
1198 <returns>cookie string</returns>
1884 </member> 1199 </member>
1885 <member name="P:HttpServer.HttpClientContext.CurrentRequest"> 1200 <member name="P:HttpServer.RequestCookie.Name">
1886 <summary> 1201 <summary>
1887 Overload to specify own type. 1202 Gets the cookie identifier.
1888 </summary> 1203 </summary>
1889 <remarks>
1890 Must be specified before the context is being used.
1891 </remarks>
1892 </member> 1204 </member>
1893 <member name="P:HttpServer.HttpClientContext.Secured"> 1205 <member name="P:HttpServer.RequestCookie.Value">
1894 <summary> 1206 <summary>
1895 Using SSL or other encryption method. 1207 Cookie value. Set to null to remove cookie.
1896 </summary> 1208 </summary>
1897 </member> 1209 </member>
1898 <member name="P:HttpServer.HttpClientContext.IsSecured"> 1210 <member name="M:HttpServer.ResponseCookie.#ctor(System.String,System.String,System.DateTime)">
1899 <summary> 1211 <summary>
1900 Using SSL or other encryption method. 1212 Constructor.
1901 </summary> 1213 </summary>
1214 <param name="id">cookie identifier</param>
1215 <param name="content">cookie content</param>
1216 <param name="expiresAt">cookie expiration date. Use DateTime.MinValue for session cookie.</param>
1217 <exception cref="T:System.ArgumentNullException">id or content is null</exception>
1218 <exception cref="T:System.ArgumentException">id is empty</exception>
1902 </member> 1219 </member>
1903 <member name="P:HttpServer.HttpClientContext.LogWriter"> 1220 <member name="M:HttpServer.ResponseCookie.#ctor(System.String,System.String,System.DateTime,System.String,System.String)">
1904 <summary> 1221 <summary>
1905 Specify which logger to use. 1222 Create a new cookie
1906 </summary> 1223 </summary>
1224 <param name="name">name identifying the cookie</param>
1225 <param name="value">cookie value</param>
1226 <param name="expires">when the cookie expires. Setting DateTime.MinValue will delete the cookie when the session is closed.</param>
1227 <param name="path">Path to where the cookie is valid</param>
1228 <param name="domain">Domain that the cookie is valid for.</param>
1907 </member> 1229 </member>
1908 <member name="P:HttpServer.HttpClientContext.Stream"> 1230 <member name="M:HttpServer.ResponseCookie.#ctor(HttpServer.RequestCookie,System.DateTime)">
1909 <summary> 1231 <summary>
1910 Gets or sets the network stream. 1232 Create a new cookie
1911 </summary> 1233 </summary>
1234 <param name="cookie">Name and value will be used</param>
1235 <param name="expires">when the cookie expires.</param>
1912 </member> 1236 </member>
1913 <member name="P:HttpServer.HttpClientContext.RemoteAddress"> 1237 <member name="M:HttpServer.ResponseCookie.ToString">
1914 <summary> 1238 <summary>
1915 Gets or sets IP address that the client connected from. 1239 Gets the cookie HTML representation.
1916 </summary> 1240 </summary>
1241 <returns>cookie string</returns>
1917 </member> 1242 </member>
1918 <member name="P:HttpServer.HttpClientContext.RemotePort"> 1243 <member name="P:HttpServer.ResponseCookie.Expires">
1919 <summary> 1244 <summary>
1920 Gets or sets port that the client connected from. 1245 When the cookie expires.
1246 DateTime.MinValue means that the cookie expires when the session do so.
1921 </summary> 1247 </summary>
1922 </member> 1248 </member>
1923 <member name="E:HttpServer.HttpClientContext.Disconnected"> 1249 <member name="P:HttpServer.ResponseCookie.Path">
1924 <summary> 1250 <summary>
1925 The context have been disconnected. 1251 Cookie is only valid under this path.
1926 </summary> 1252 </summary>
1927 <remarks>
1928 Event can be used to clean up a context, or to reuse it.
1929 </remarks>
1930 </member> 1253 </member>
1931 <member name="E:HttpServer.HttpClientContext.RequestReceived"> 1254 <member name="T:HttpServer.IComponentProvider">
1932 <summary> 1255 <summary>
1933 A request have been received in the context. 1256 Inversion of control interface.
1934 </summary> 1257 </summary>
1935 </member> 1258 </member>
1936 <member name="T:HttpServer.Helpers.XmlHelper"> 1259 <member name="M:HttpServer.IComponentProvider.AddInstance``1(System.Object)">
1937 <summary> 1260 <summary>
1938 Helpers to make XML handling easier 1261 Add a component instance
1939 </summary> 1262 </summary>
1263 <typeparam name="T">Interface type</typeparam>
1264 <param name="instance">Instance to add</param>
1940 </member> 1265 </member>
1941 <member name="M:HttpServer.Helpers.XmlHelper.Serialize(System.Object)"> 1266 <member name="M:HttpServer.IComponentProvider.Get``1">
1942 <summary> 1267 <summary>
1943 Serializes object to XML. 1268 Get a component.
1944 </summary> 1269 </summary>
1945 <param name="value">object to serialize.</param> 1270 <typeparam name="T">Interface type</typeparam>
1946 <returns>XML</returns> 1271 <returns>Component if registered, otherwise null.</returns>
1947 <remarks> 1272 <remarks>
1948 Removes name spaces and adds indentation 1273 Component will get created if needed.
1949 </remarks> 1274 </remarks>
1950 </member> 1275 </member>
1951 <member name="M:HttpServer.Helpers.XmlHelper.Deserialize``1(System.String)"> 1276 <member name="M:HttpServer.IComponentProvider.Contains(System.Type)">
1952 <summary>
1953 Create an object from a XML string
1954 </summary>
1955 <typeparam name="T">Type of object</typeparam>
1956 <param name="xml">XML string</param>
1957 <returns>object</returns>
1958 </member>
1959 <member name="T:HttpServer.FormDecoders.UrlDecoder">
1960 <summary> 1277 <summary>
1961 Can handle application/x-www-form-urlencoded 1278 Checks if the specified component interface have been added.
1962 </summary> 1279 </summary>
1280 <param name="interfaceType"></param>
1281 <returns>true if found; otherwise false.</returns>
1963 </member> 1282 </member>
1964 <member name="M:HttpServer.FormDecoders.UrlDecoder.Decode(System.IO.Stream,System.String,System.Text.Encoding)"> 1283 <member name="M:HttpServer.IComponentProvider.Add``2">
1965 <summary> 1284 <summary>
1285 Add a component.
1966 </summary> 1286 </summary>
1967 <param name="stream">Stream containing the content</param> 1287 <typeparam name="InterfaceType">Type being requested.</typeparam>
1968 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case</param> 1288 <typeparam name="InstanceType">Type being created.</typeparam>
1969 <param name="encoding">Stream encoding</param>
1970 <returns>
1971 A HTTP form, or null if content could not be parsed.
1972 </returns>
1973 <exception cref="T:System.IO.InvalidDataException">If contents in the stream is not valid input data.</exception>
1974 </member> 1289 </member>
1975 <member name="M:HttpServer.FormDecoders.UrlDecoder.CanParse(System.String)"> 1290 <member name="T:HttpServer.HttpListenerBase">
1976 <summary> 1291 <summary>
1977 Checks if the decoder can handle the mime type 1292 Contains a listener that doesn't do anything with the connections.
1978 </summary> 1293 </summary>
1979 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case.</param>
1980 <returns>True if the decoder can parse the specified content type</returns>
1981 </member> 1294 </member>
1982 <member name="T:HttpServer.ClientAcceptedEventArgs"> 1295 <member name="M:HttpServer.HttpListenerBase.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory)">
1983 <summary> 1296 <summary>
1984 Invoked when a client have been accepted by the <see cref="T:HttpServer.HttpListener"/> 1297 Listen for regular HTTP connections
1985 </summary> 1298 </summary>
1986 <remarks> 1299 <param name="address">IP Address to accept connections on</param>
1987 Can be used to revoke incoming connections 1300 <param name="port">TCP Port to listen on, default HTTP port is 80.</param>
1988 </remarks> 1301 <param name="factory">Factory used to create <see cref="T:HttpServer.IHttpClientContext"/>es.</param>
1302 <exception cref="T:System.ArgumentNullException"><c>address</c> is null.</exception>
1303 <exception cref="T:System.ArgumentException">Port must be a positive number.</exception>
1989 </member> 1304 </member>
1990 <member name="M:HttpServer.ClientAcceptedEventArgs.#ctor(System.Net.Sockets.Socket)"> 1305 <member name="M:HttpServer.HttpListenerBase.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory,System.Security.Cryptography.X509Certificates.X509Certificate)">
1991 <summary> 1306 <summary>
1992 Initializes a new instance of the <see cref="T:HttpServer.ClientAcceptedEventArgs"/> class. 1307 Initializes a new instance of the <see cref="T:HttpServer.HttpListenerBase"/> class.
1993 </summary> 1308 </summary>
1994 <param name="socket">The socket.</param> 1309 <param name="address">IP Address to accept connections on</param>
1310 <param name="port">TCP Port to listen on, default HTTPS port is 443</param>
1311 <param name="factory">Factory used to create <see cref="T:HttpServer.IHttpClientContext"/>es.</param>
1312 <param name="certificate">Certificate to use</param>
1995 </member> 1313 </member>
1996 <member name="M:HttpServer.ClientAcceptedEventArgs.Revoke"> 1314 <member name="M:HttpServer.HttpListenerBase.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory,System.Security.Cryptography.X509Certificates.X509Certificate,System.Security.Authentication.SslProtocols)">
1997 <summary> 1315 <summary>
1998 Client may not be handled. 1316 Initializes a new instance of the <see cref="T:HttpServer.HttpListenerBase"/> class.
1999 </summary> 1317 </summary>
1318 <param name="address">IP Address to accept connections on</param>
1319 <param name="port">TCP Port to listen on, default HTTPS port is 443</param>
1320 <param name="factory">Factory used to create <see cref="T:HttpServer.IHttpClientContext"/>es.</param>
1321 <param name="certificate">Certificate to use</param>
1322 <param name="protocol">which HTTPS protocol to use, default is TLS.</param>
2000 </member> 1323 </member>
2001 <member name="P:HttpServer.ClientAcceptedEventArgs.Socket"> 1324 <member name="M:HttpServer.HttpListenerBase.OnAccept(System.IAsyncResult)">
2002 <summary> 1325 <exception cref="T:System.Exception"><c>Exception</c>.</exception>
2003 Accepted socket.
2004 </summary>
2005 </member> 1326 </member>
2006 <member name="P:HttpServer.ClientAcceptedEventArgs.Revoked"> 1327 <member name="M:HttpServer.HttpListenerBase.RetryBeginAccept">
2007 <summary> 1328 <summary>
2008 Client should be revoked. 1329 Will try to accept connections one more time.
2009 </summary> 1330 </summary>
1331 <exception cref="T:System.Exception">If any exceptions is thrown.</exception>
2010 </member> 1332 </member>
2011 <member name="T:HttpServer.Sessions.HttpSessionClearedArgs"> 1333 <member name="M:HttpServer.HttpListenerBase.OnAcceptingSocket(System.Net.Sockets.Socket)">
2012 <summary> 1334 <summary>
2013 Arguments sent when a <see cref="T:HttpServer.Sessions.IHttpSession"/> is cleared 1335 Can be used to create filtering of new connections.
2014 </summary> 1336 </summary>
1337 <param name="socket">Accepted socket</param>
1338 <returns>true if connection can be accepted; otherwise false.</returns>
2015 </member> 1339 </member>
2016 <member name="M:HttpServer.Sessions.HttpSessionClearedArgs.#ctor(System.Boolean)"> 1340 <member name="M:HttpServer.HttpListenerBase.Start(System.Int32)">
2017 <summary> 1341 <summary>
2018 Instantiates the arguments for the event 1342 Start listen for new connections
2019 </summary> 1343 </summary>
2020 <param name="expired">True if the session is cleared due to expiration</param> 1344 <param name="backlog">Number of connections that can stand in a queue to be accepted.</param>
1345 <exception cref="T:System.InvalidOperationException">Listener have already been started.</exception>
2021 </member> 1346 </member>
2022 <member name="P:HttpServer.Sessions.HttpSessionClearedArgs.Expired"> 1347 <member name="M:HttpServer.HttpListenerBase.Stop">
2023 <summary> 1348 <summary>
2024 Returns true if the session is cleared due to expiration 1349 Stop the listener
2025 </summary> 1350 </summary>
1351 <exception cref="T:System.Net.Sockets.SocketException"></exception>
2026 </member> 1352 </member>
2027 <member name="T:HttpServer.Sessions.HttpSessionClearedHandler"> 1353 <member name="P:HttpServer.HttpListenerBase.LogWriter">
2028 <summary> 1354 <summary>
2029 Delegate for when a IHttpSession is cleared 1355 Gives you a change to receive log entries for all internals of the HTTP library.
2030 </summary> 1356 </summary>
2031 <param name="session"><see cref="T:HttpServer.Sessions.IHttpSession"/> this is being cleared.</param> 1357 <remarks>
2032 <param name="args">Arguments for the clearing</param> 1358 You may not switch log writer after starting the listener.
1359 </remarks>
2033 </member> 1360 </member>
2034 <member name="T:HttpServer.Parser.HeaderEventArgs"> 1361 <member name="P:HttpServer.HttpListenerBase.UseTraceLogs">
2035 <summary> 1362 <summary>
2036 Event arguments used when a new header have been parsed. 1363 True if we should turn on trace logs.
2037 </summary> 1364 </summary>
2038 </member> 1365 </member>
2039 <member name="M:HttpServer.Parser.HeaderEventArgs.#ctor(System.String,System.String)"> 1366 <member name="E:HttpServer.HttpListenerBase.ExceptionThrown">
2040 <summary> 1367 <summary>
2041 Initializes a new instance of the <see cref="T:HttpServer.Parser.HeaderEventArgs"/> class. 1368 Catch exceptions not handled by the listener.
2042 </summary> 1369 </summary>
2043 <param name="name">Name of header.</param> 1370 <remarks>
2044 <param name="value">Header value.</param> 1371 Exceptions will be thrown during debug mode if this event is not used,
1372 exceptions will be printed to console and suppressed during release mode.
1373 </remarks>
2045 </member> 1374 </member>
2046 <member name="M:HttpServer.Parser.HeaderEventArgs.#ctor"> 1375 <member name="E:HttpServer.HttpListenerBase.RequestReceived">
2047 <summary> 1376 <summary>
2048 Initializes a new instance of the <see cref="T:HttpServer.Parser.HeaderEventArgs"/> class. 1377 A request have been received from a <see cref="T:HttpServer.IHttpClientContext"/>.
2049 </summary> 1378 </summary>
2050 </member> 1379 </member>
2051 <member name="P:HttpServer.Parser.HeaderEventArgs.Name"> 1380 <member name="T:HttpServer.HttpListener">
2052 <summary> 1381 <summary>
2053 Gets or sets header name. 1382 New implementation of the HTTP listener.
2054 </summary> 1383 </summary>
1384 <remarks>
1385 Use the <c>Create</c> methods to create a default listener.
1386 </remarks>
2055 </member> 1387 </member>
2056 <member name="P:HttpServer.Parser.HeaderEventArgs.Value"> 1388 <member name="M:HttpServer.HttpListener.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory)">
2057 <summary> 1389 <summary>
2058 Gets or sets header value. 1390 Initializes a new instance of the <see cref="T:HttpServer.HttpListener"/> class.
2059 </summary> 1391 </summary>
1392 <param name="address">IP Address to accept connections on</param>
1393 <param name="port">TCP Port to listen on, default HTTP port is 80.</param>
1394 <param name="factory">Factory used to create <see cref="T:HttpServer.IHttpClientContext"/>es.</param>
1395 <exception cref="T:System.ArgumentNullException"><c>address</c> is null.</exception>
1396 <exception cref="T:System.ArgumentException">Port must be a positive number.</exception>
2060 </member> 1397 </member>
2061 <member name="T:HttpServer.Helpers.ResourceManager"> 1398 <member name="M:HttpServer.HttpListener.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory,System.Security.Cryptography.X509Certificates.X509Certificate)">
2062 <summary>Class to handle loading of resource files</summary>
2063 </member>
2064 <member name="M:HttpServer.Helpers.ResourceManager.#ctor">
2065 <summary> 1399 <summary>
2066 Initializes a new instance of the <see cref="T:HttpServer.Helpers.ResourceManager"/> class. 1400 Initializes a new instance of the <see cref="T:HttpServer.HttpListener"/> class.
2067 </summary> 1401 </summary>
1402 <param name="address">The address.</param>
1403 <param name="port">The port.</param>
1404 <param name="factory">The factory.</param>
1405 <param name="certificate">The certificate.</param>
2068 </member> 1406 </member>
2069 <member name="M:HttpServer.Helpers.ResourceManager.#ctor(HttpServer.ILogWriter)"> 1407 <member name="M:HttpServer.HttpListener.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory,System.Security.Cryptography.X509Certificates.X509Certificate,System.Security.Authentication.SslProtocols)">
2070 <summary> 1408 <summary>
2071 Initializes a new instance of the <see cref="T:HttpServer.Helpers.ResourceManager"/> class. 1409 Initializes a new instance of the <see cref="T:HttpServer.HttpListener"/> class.
2072 </summary> 1410 </summary>
2073 <param name="writer">logger.</param> 1411 <param name="address">The address.</param>
1412 <param name="port">The port.</param>
1413 <param name="factory">The factory.</param>
1414 <param name="certificate">The certificate.</param>
1415 <param name="protocol">The protocol.</param>
2074 </member> 1416 </member>
2075 <member name="M:HttpServer.Helpers.ResourceManager.LoadResources(System.String,System.Reflection.Assembly,System.String)"> 1417 <member name="M:HttpServer.HttpListener.Create(System.Net.IPAddress,System.Int32)">
2076 <summary> 1418 <summary>
2077 Loads resources from a namespace in the given assembly to an URI 1419 Creates a new <see cref="T:HttpServer.HttpListener"/> instance with default factories.
2078 </summary> 1420 </summary>
2079 <param name="toUri">The URI to map the resources to</param> 1421 <param name="address">Address that the listener should accept connections on.</param>
2080 <param name="fromAssembly">The assembly in which the resources reside</param> 1422 <param name="port">Port that listener should accept connections on.</param>
2081 <param name="fromNamespace">The namespace from which to load the resources</param> 1423 <returns>Created HTTP listener.</returns>
2082 <usage>
2083 <code>
2084 resourceLoader.LoadResources("/user/", typeof(User).Assembly, "MyLib.Models.User.Views");
2085 </code>
2086 Will make the resource MyLib.Models.User.Views.list.Haml accessible via /user/list.haml or /user/list/
2087 </usage>
2088 <returns>The amount of loaded files, giving you the possibility of making sure the resources needed gets loaded</returns>
2089 <exception cref="T:System.InvalidOperationException">If a resource has already been mapped to an uri</exception>
2090 </member> 1424 </member>
2091 <member name="M:HttpServer.Helpers.ResourceManager.GetResourceStream(System.String)"> 1425 <member name="M:HttpServer.HttpListener.Create(System.Net.IPAddress,System.Int32,System.Security.Cryptography.X509Certificates.X509Certificate)">
2092 <summary> 1426 <summary>
2093 Retrieves a stream for the specified resource path if loaded otherwise null 1427 Creates a new <see cref="T:HttpServer.HttpListener"/> instance with default factories.
2094 </summary> 1428 </summary>
2095 <param name="path">Path to the resource to retrieve a stream for</param> 1429 <param name="address">Address that the listener should accept connections on.</param>
2096 <returns>A stream or null if the resource couldn't be found</returns> 1430 <param name="port">Port that listener should accept connections on.</param>
1431 <param name="certificate">Certificate to use</param>
1432 <returns>Created HTTP listener.</returns>
2097 </member> 1433 </member>
2098 <member name="M:HttpServer.Helpers.ResourceManager.GetFiles(System.String)"> 1434 <member name="M:HttpServer.HttpListener.Create(System.Net.IPAddress,System.Int32,System.Security.Cryptography.X509Certificates.X509Certificate,System.Security.Authentication.SslProtocols)">
2099 <summary> 1435 <summary>
2100 Fetch all files from the resource that matches the specified arguments. 1436 Creates a new <see cref="T:HttpServer.HttpListener"/> instance with default factories.
2101 </summary> 1437 </summary>
2102 <param name="path">The path to the resource to extract</param> 1438 <param name="address">Address that the listener should accept connections on.</param>
2103 <returns> 1439 <param name="port">Port that listener should accept connections on.</param>
2104 a list of files if found; or an empty array if no files are found. 1440 <param name="certificate">Certificate to use</param>
2105 </returns> 1441 <param name="protocol">which HTTPS protocol to use, default is TLS.</param>
2106 <exception cref="T:System.ArgumentException">Search path must end with an asterisk for finding arbitrary files</exception> 1442 <returns>Created HTTP listener.</returns>
2107 </member> 1443 </member>
2108 <member name="M:HttpServer.Helpers.ResourceManager.GetFiles(System.String,System.String)"> 1444 <member name="M:HttpServer.HttpListener.OnAcceptingSocket(System.Net.Sockets.Socket)">
2109 <summary> 1445 <summary>
2110 Fetch all files from the resource that matches the specified arguments. 1446 Can be used to create filtering of new connections.
2111 </summary> 1447 </summary>
2112 <param name="path">Where the file should reside.</param> 1448 <param name="socket">Accepted socket</param>
2113 <param name="filename">Files to check</param>
2114 <returns> 1449 <returns>
2115 a list of files if found; or an empty array if no files are found. 1450 true if connection can be accepted; otherwise false.
2116 </returns> 1451 </returns>
2117 </member> 1452 </member>
2118 <member name="M:HttpServer.Helpers.ResourceManager.ContainsResource(System.String)"> 1453 <member name="E:HttpServer.HttpListener.Accepted">
2119 <summary> 1454 <summary>
2120 Returns whether or not the loader has an instance of the file requested 1455 A client have been accepted, but not handled, by the listener.
2121 </summary> 1456 </summary>
2122 <param name="filename">The name of the template/file</param>
2123 <returns>True if the loader can provide the file</returns>
2124 </member> 1457 </member>
2125 <member name="T:HttpServer.Rules.RedirectRule"> 1458 <member name="T:HttpServer.Rules.RedirectRule">
2126 <summary> 1459 <summary>
@@ -2200,50 +1533,6 @@
2200 <c>true</c> means that a redirect response is sent to the client. 1533 <c>true</c> means that a redirect response is sent to the client.
2201 </remarks> 1534 </remarks>
2202 </member> 1535 </member>
2203 <member name="T:HttpServer.RequestQueue">
2204 <summary>
2205 Used to queue incoming requests.
2206 </summary>
2207 </member>
2208 <member name="M:HttpServer.RequestQueue.#ctor(HttpServer.ProcessRequestHandler)">
2209 <summary>
2210 Initializes a new instance of the <see cref="T:HttpServer.RequestQueue"/> class.
2211 </summary>
2212 <param name="handler">Called when a request should be processed.</param>
2213 </member>
2214 <member name="M:HttpServer.RequestQueue.QueueThread">
2215 <summary>
2216 Used to process queued requests.
2217 </summary>
2218 </member>
2219 <member name="P:HttpServer.RequestQueue.MaxRequestCount">
2220 <summary>
2221 Gets or sets maximum number of allowed simultaneous requests.
2222 </summary>
2223 </member>
2224 <member name="P:HttpServer.RequestQueue.MaxQueueSize">
2225 <summary>
2226 Gets or sets maximum number of requests queuing to be handled.
2227 </summary>
2228 </member>
2229 <member name="P:HttpServer.RequestQueue.CurrentRequestCount">
2230 <summary>
2231 Specifies how many requests the HTTP server is currently processing.
2232 </summary>
2233 </member>
2234 <member name="T:HttpServer.RequestQueue.QueueItem">
2235 <summary>
2236 Used two queue incoming requests to avoid
2237 thread starvation.
2238 </summary>
2239 </member>
2240 <member name="T:HttpServer.ProcessRequestHandler">
2241 <summary>
2242 Method used to process a queued request
2243 </summary>
2244 <param name="context">Context that the request was received from.</param>
2245 <param name="request">Request to process.</param>
2246 </member>
2247 <member name="T:HttpServer.Parser.HttpRequestParser"> 1536 <member name="T:HttpServer.Parser.HttpRequestParser">
2248 <summary> 1537 <summary>
2249 Parses a HTTP request directly from a stream 1538 Parses a HTTP request directly from a stream
@@ -2380,516 +1669,349 @@
2380 A header have been received. 1669 A header have been received.
2381 </summary> 1670 </summary>
2382 </member> 1671 </member>
2383 <member name="T:HttpServer.IHttpResponse"> 1672 <member name="T:HttpServer.IHttpRequest">
2384 <summary>
2385 Response that is sent back to the web browser / client.
2386
2387 A response can be sent if different ways. The easiest one is
2388 to just fill the Body stream with content, everything else
2389 will then be taken care of by the framework. The default content-type
2390 is text/html, you should change it if you send anything else.
2391
2392 The second and slighty more complex way is to send the response
2393 as parts. Start with sending the header using the SendHeaders method and
2394 then you can send the body using SendBody method, but do not forget
2395 to set ContentType and ContentLength before doing so.
2396 </summary>
2397 <example>
2398 public void MyHandler(IHttpRequest request, IHttpResponse response)
2399 {
2400
2401 }
2402 </example>
2403 </member>
2404 <member name="M:HttpServer.IHttpResponse.AddHeader(System.String,System.String)">
2405 <summary>
2406 Add another header to the document.
2407 </summary>
2408 <param name="name">Name of the header, case sensitive, use lower cases.</param>
2409 <param name="value">Header values can span over multiple lines as long as each line starts with a white space. New line chars should be \r\n</param>
2410 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
2411 <exception cref="T:System.ArgumentException">If value conditions have not been met.</exception>
2412 <remarks>Adding any header will override the default ones and those specified by properties.</remarks>
2413 </member>
2414 <member name="M:HttpServer.IHttpResponse.Send">
2415 <summary>
2416 Send headers and body to the browser.
2417 </summary>
2418 <exception cref="T:System.InvalidOperationException">If content have already been sent.</exception>
2419 </member>
2420 <member name="M:HttpServer.IHttpResponse.SendBody(System.Byte[],System.Int32,System.Int32)">
2421 <summary>
2422 Make sure that you have specified ContentLength and sent the headers first.
2423 </summary>
2424 <param name="buffer"></param>
2425 <exception cref="T:System.InvalidOperationException">If headers have not been sent.</exception>
2426 <see cref="M:HttpServer.IHttpResponse.SendHeaders"/>
2427 <param name="offset">offest of first byte to send</param>
2428 <param name="count">number of bytes to send.</param>
2429 <seealso cref="M:HttpServer.IHttpResponse.Send"/>
2430 <seealso cref="M:HttpServer.IHttpResponse.SendHeaders"/>
2431 <remarks>This method can be used if you want to send body contents without caching them first. This
2432 is recommended for larger files to keep the memory usage low.</remarks>
2433 </member>
2434 <member name="M:HttpServer.IHttpResponse.SendBody(System.Byte[])">
2435 <summary>
2436 Make sure that you have specified ContentLength and sent the headers first.
2437 </summary>
2438 <param name="buffer"></param>
2439 <exception cref="T:System.InvalidOperationException">If headers have not been sent.</exception>
2440 <see cref="M:HttpServer.IHttpResponse.SendHeaders"/>
2441 <seealso cref="M:HttpServer.IHttpResponse.Send"/>
2442 <seealso cref="M:HttpServer.IHttpResponse.SendHeaders"/>
2443 <remarks>This method can be used if you want to send body contents without caching them first. This
2444 is recommended for larger files to keep the memory usage low.</remarks>
2445 </member>
2446 <member name="M:HttpServer.IHttpResponse.SendHeaders">
2447 <summary>
2448 Send headers to the client.
2449 </summary>
2450 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
2451 <seealso cref="M:HttpServer.IHttpResponse.AddHeader(System.String,System.String)"/>
2452 <seealso cref="M:HttpServer.IHttpResponse.Send"/>
2453 <seealso cref="M:HttpServer.IHttpResponse.SendBody(System.Byte[])"/>
2454 </member>
2455 <member name="M:HttpServer.IHttpResponse.Redirect(System.Uri)">
2456 <summary>
2457 Redirect client to somewhere else using the 302 status code.
2458 </summary>
2459 <param name="uri">Destination of the redirect</param>
2460 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
2461 <remarks>You can not do anything more with the request when a redirect have been done. This should be your last
2462 action.</remarks>
2463 </member>
2464 <member name="M:HttpServer.IHttpResponse.Redirect(System.String)">
2465 <summary>
2466 redirect to somewhere
2467 </summary>
2468 <param name="url">where the redirect should go</param>
2469 <remarks>
2470 No body are allowed when doing redirects.
2471 </remarks>
2472 </member>
2473 <member name="P:HttpServer.IHttpResponse.Body">
2474 <summary>
2475 The body stream is used to cache the body contents
2476 before sending everything to the client. It's the simplest
2477 way to serve documents.
2478 </summary>
2479 </member>
2480 <member name="P:HttpServer.IHttpResponse.ProtocolVersion">
2481 <summary> 1673 <summary>
2482 Defines the version of the HTTP Response for applications where it's required 1674 Contains server side HTTP request information.
2483 for this to be forced.
2484 </summary> 1675 </summary>
2485 </member> 1676 </member>
2486 <member name="P:HttpServer.IHttpResponse.Chunked"> 1677 <member name="M:HttpServer.IHttpRequest.AddHeader(System.String,System.String)">
2487 <summary> 1678 <summary>
2488 The chunked encoding modifies the body of a message in order to 1679 Called during parsing of a <see cref="T:HttpServer.IHttpRequest"/>.
2489 transfer it as a series of chunks, each with its own size indicator,
2490 followed by an OPTIONAL trailer containing entity-header fields. This
2491 allows dynamically produced content to be transferred along with the
2492 information necessary for the recipient to verify that it has
2493 received the full message.
2494 </summary> 1680 </summary>
1681 <param name="name">Name of the header, should not be URL encoded</param>
1682 <param name="value">Value of the header, should not be URL encoded</param>
1683 <exception cref="T:HttpServer.Exceptions.BadRequestException">If a header is incorrect.</exception>
2495 </member> 1684 </member>
2496 <member name="P:HttpServer.IHttpResponse.Connection"> 1685 <member name="M:HttpServer.IHttpRequest.AddToBody(System.Byte[],System.Int32,System.Int32)">
2497 <summary> 1686 <summary>
2498 Kind of connection 1687 Add bytes to the body
2499 </summary> 1688 </summary>
1689 <param name="bytes">buffer to read bytes from</param>
1690 <param name="offset">where to start read</param>
1691 <param name="length">number of bytes to read</param>
1692 <returns>Number of bytes actually read (same as length unless we got all body bytes).</returns>
1693 <exception cref="T:System.InvalidOperationException">If body is not writable</exception>
1694 <exception cref="T:System.ArgumentNullException"><c>bytes</c> is null.</exception>
1695 <exception cref="T:System.ArgumentOutOfRangeException"><c>offset</c> is out of range.</exception>
2500 </member> 1696 </member>
2501 <member name="P:HttpServer.IHttpResponse.Encoding"> 1697 <member name="M:HttpServer.IHttpRequest.Clear">
2502 <summary> 1698 <summary>
2503 Encoding to use when sending stuff to the client. 1699 Clear everything in the request
2504 </summary> 1700 </summary>
2505 <remarks>Default is UTF8</remarks>
2506 </member> 1701 </member>
2507 <member name="P:HttpServer.IHttpResponse.KeepAlive"> 1702 <member name="M:HttpServer.IHttpRequest.DecodeBody(HttpServer.FormDecoders.FormDecoderProvider)">
2508 <summary> 1703 <summary>
2509 Number of seconds to keep connection alive 1704 Decode body into a form.
2510 </summary> 1705 </summary>
2511 <remarks>Only used if Connection property is set to ConnectionType.KeepAlive</remarks> 1706 <param name="providers">A list with form decoders.</param>
1707 <exception cref="T:System.IO.InvalidDataException">If body contents is not valid for the chosen decoder.</exception>
1708 <exception cref="T:System.InvalidOperationException">If body is still being transferred.</exception>
2512 </member> 1709 </member>
2513 <member name="P:HttpServer.IHttpResponse.Status"> 1710 <member name="M:HttpServer.IHttpRequest.SetCookies(HttpServer.RequestCookies)">
2514 <summary> 1711 <summary>
2515 Status code that is sent to the client. 1712 Sets the cookies.
2516 </summary> 1713 </summary>
2517 <remarks>Default is HttpStatusCode.Ok</remarks> 1714 <param name="cookies">The cookies.</param>
2518 </member> 1715 </member>
2519 <member name="P:HttpServer.IHttpResponse.Reason"> 1716 <member name="M:HttpServer.IHttpRequest.CreateResponse(HttpServer.IHttpClientContext)">
2520 <summary> 1717 <summary>
2521 Information about why a specific status code was used. 1718 Create a response object.
2522 </summary> 1719 </summary>
1720 <param name="context">Context for the connected client.</param>
1721 <returns>A new <see cref="T:HttpServer.IHttpResponse"/>.</returns>
2523 </member> 1722 </member>
2524 <member name="P:HttpServer.IHttpResponse.ContentLength"> 1723 <member name="P:HttpServer.IHttpRequest.AcceptTypes">
2525 <summary> 1724 <summary>
2526 Size of the body. MUST be specified before sending the header, 1725 Gets kind of types accepted by the client.
2527 unless property Chunked is set to true.
2528 </summary> 1726 </summary>
2529 </member> 1727 </member>
2530 <member name="P:HttpServer.IHttpResponse.ContentType"> 1728 <member name="P:HttpServer.IHttpRequest.Body">
2531 <summary> 1729 <summary>
2532 Kind of content in the body 1730 Gets or sets body stream.
2533 </summary> 1731 </summary>
2534 <remarks>Default is text/html</remarks>
2535 </member> 1732 </member>
2536 <member name="P:HttpServer.IHttpResponse.HeadersSent"> 1733 <member name="P:HttpServer.IHttpRequest.BodyIsComplete">
2537 <summary> 1734 <summary>
2538 Headers have been sent to the client- 1735 Gets whether the body is complete.
2539 </summary> 1736 </summary>
2540 <remarks>You can not send any additional headers if they have already been sent.</remarks>
2541 </member> 1737 </member>
2542 <member name="P:HttpServer.IHttpResponse.Sent"> 1738 <member name="P:HttpServer.IHttpRequest.Connection">
2543 <summary> 1739 <summary>
2544 The whole response have been sent. 1740 Gets or sets kind of connection used for the session.
2545 </summary> 1741 </summary>
2546 </member> 1742 </member>
2547 <member name="P:HttpServer.IHttpResponse.Cookies"> 1743 <member name="P:HttpServer.IHttpRequest.ContentLength">
2548 <summary> 1744 <summary>
2549 Cookies that should be created/changed. 1745 Gets or sets number of bytes in the body.
2550 </summary> 1746 </summary>
2551 </member> 1747 </member>
2552 <member name="T:HttpServer.ConnectionType"> 1748 <member name="P:HttpServer.IHttpRequest.Cookies">
2553 <summary> 1749 <summary>
2554 Type of HTTP connection 1750 Gets cookies that was sent with the request.
2555 </summary> 1751 </summary>
2556 </member> 1752 </member>
2557 <member name="F:HttpServer.ConnectionType.Close"> 1753 <member name="P:HttpServer.IHttpRequest.Form">
2558 <summary> 1754 <summary>
2559 Connection is closed after each request-response 1755 Gets form parameters.
2560 </summary> 1756 </summary>
2561 </member> 1757 </member>
2562 <member name="F:HttpServer.ConnectionType.KeepAlive"> 1758 <member name="P:HttpServer.IHttpRequest.Headers">
2563 <summary> 1759 <summary>
2564 Connection is kept alive for X seconds (unless another request have been made) 1760 Gets headers sent by the client.
2565 </summary> 1761 </summary>
2566 </member> 1762 </member>
2567 <member name="T:HttpServer.HttpResponse"> 1763 <member name="P:HttpServer.IHttpRequest.HttpVersion">
2568 <summary> 1764 <summary>
2569 Response that is sent back to the web browser / client. 1765 Gets or sets version of HTTP protocol that's used.
2570 </summary> 1766 </summary>
2571 <remarks> 1767 <remarks>
2572 <para> 1768 Probably <see cref="F:HttpServer.HttpHelper.HTTP10"/> or <see cref="F:HttpServer.HttpHelper.HTTP11"/>.
2573 A response can be sent if different ways. The easiest one is
2574 to just fill the Body stream with content, everything else
2575 will then be taken care of by the framework. The default content-type
2576 is text/html, you should change it if you send anything else.
2577 </para><para>
2578 The second and slightly more complex way is to send the response
2579 as parts. Start with sending the header using the SendHeaders method and
2580 then you can send the body using SendBody method, but do not forget
2581 to set <see cref="P:HttpServer.HttpResponse.ContentType"/> and <see cref="P:HttpServer.HttpResponse.ContentLength"/> before doing so.
2582 </para>
2583 </remarks> 1769 </remarks>
2584 <example> 1770 <seealso cref="T:HttpServer.HttpHelper"/>
2585 <code>
2586 // Example using response body.
2587 class MyModule : HttpModule
2588 {
2589 public override bool Process(IHttpRequest request, IHttpResponse response, IHttpSession session)
2590 {
2591 StreamWriter writer = new StreamWriter(response.Body);
2592 writer.WriteLine("Hello dear World!");
2593 writer.Flush();
2594
2595 // return true to tell webserver that we've handled the url
2596 return true;
2597 }
2598 }
2599 </code>
2600 </example>
2601 todo: add two examples, using SendHeaders/SendBody and just the Body stream.
2602 </member>
2603 <member name="M:HttpServer.HttpResponse.#ctor(HttpServer.IHttpClientContext,HttpServer.IHttpRequest)">
2604 <summary>
2605 Initializes a new instance of the <see cref="T:HttpServer.IHttpResponse"/> class.
2606 </summary>
2607 <param name="context">Client that send the <see cref="T:HttpServer.IHttpRequest"/>.</param>
2608 <param name="request">Contains information of what the client want to receive.</param>
2609 <exception cref="T:System.ArgumentException"><see cref="P:HttpServer.IHttpRequest.HttpVersion"/> cannot be empty.</exception>
2610 </member>
2611 <member name="M:HttpServer.HttpResponse.#ctor(HttpServer.IHttpClientContext,System.String,HttpServer.ConnectionType)">
2612 <summary>
2613 Initializes a new instance of the <see cref="T:HttpServer.IHttpResponse"/> class.
2614 </summary>
2615 <param name="context">Client that send the <see cref="T:HttpServer.IHttpRequest"/>.</param>
2616 <param name="httpVersion">Version of HTTP protocol that the client uses.</param>
2617 <param name="connectionType">Type of HTTP connection used.</param>
2618 </member>
2619 <member name="M:HttpServer.HttpResponse.AddHeader(System.String,System.String)">
2620 <summary>
2621 Add another header to the document.
2622 </summary>
2623 <param name="name">Name of the header, case sensitive, use lower cases.</param>
2624 <param name="value">Header values can span over multiple lines as long as each line starts with a white space. New line chars should be \r\n</param>
2625 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
2626 <exception cref="T:System.ArgumentException">If value conditions have not been met.</exception>
2627 <remarks>Adding any header will override the default ones and those specified by properties.</remarks>
2628 </member>
2629 <member name="M:HttpServer.HttpResponse.Send">
2630 <summary>
2631 Send headers and body to the browser.
2632 </summary>
2633 <exception cref="T:System.InvalidOperationException">If content have already been sent.</exception>
2634 </member>
2635 <member name="M:HttpServer.HttpResponse.SendBody(System.Byte[],System.Int32,System.Int32)">
2636 <summary>
2637 Make sure that you have specified <see cref="P:HttpServer.HttpResponse.ContentLength"/> and sent the headers first.
2638 </summary>
2639 <param name="buffer"></param>
2640 <exception cref="T:System.InvalidOperationException">If headers have not been sent.</exception>
2641 <see cref="M:HttpServer.HttpResponse.SendHeaders"/>
2642 <param name="offset">offset of first byte to send</param>
2643 <param name="count">number of bytes to send.</param>
2644 <seealso cref="M:HttpServer.HttpResponse.Send"/>
2645 <seealso cref="M:HttpServer.HttpResponse.SendHeaders"/>
2646 <remarks>This method can be used if you want to send body contents without caching them first. This
2647 is recommended for larger files to keep the memory usage low.</remarks>
2648 </member>
2649 <member name="M:HttpServer.HttpResponse.SendBody(System.Byte[])">
2650 <summary>
2651 Make sure that you have specified <see cref="P:HttpServer.HttpResponse.ContentLength"/> and sent the headers first.
2652 </summary>
2653 <param name="buffer"></param>
2654 <exception cref="T:System.InvalidOperationException">If headers have not been sent.</exception>
2655 <see cref="M:HttpServer.HttpResponse.SendHeaders"/>
2656 <seealso cref="M:HttpServer.HttpResponse.Send"/>
2657 <seealso cref="M:HttpServer.HttpResponse.SendHeaders"/>
2658 <remarks>This method can be used if you want to send body contents without caching them first. This
2659 is recommended for larger files to keep the memory usage low.</remarks>
2660 </member>
2661 <member name="M:HttpServer.HttpResponse.SendHeaders">
2662 <summary>
2663 Send headers to the client.
2664 </summary>
2665 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
2666 <seealso cref="M:HttpServer.HttpResponse.AddHeader(System.String,System.String)"/>
2667 <seealso cref="M:HttpServer.HttpResponse.Send"/>
2668 <seealso cref="M:HttpServer.HttpResponse.SendBody(System.Byte[])"/>
2669 </member> 1771 </member>
2670 <member name="M:HttpServer.HttpResponse.Redirect(System.Uri)"> 1772 <member name="P:HttpServer.IHttpRequest.IsAjax">
2671 <summary> 1773 <summary>
2672 Redirect client to somewhere else using the 302 status code. 1774 Gets whether the request was made by Ajax (Asynchronous JavaScript)
2673 </summary> 1775 </summary>
2674 <param name="uri">Destination of the redirect</param>
2675 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
2676 <remarks>You can not do anything more with the request when a redirect have been done. This should be your last
2677 action.</remarks>
2678 </member> 1776 </member>
2679 <member name="M:HttpServer.HttpResponse.Redirect(System.String)"> 1777 <member name="P:HttpServer.IHttpRequest.Method">
2680 <summary> 1778 <summary>
2681 redirect to somewhere 1779 Gets or sets requested method.
2682 </summary> 1780 </summary>
2683 <param name="url">where the redirect should go</param>
2684 <remarks> 1781 <remarks>
2685 No body are allowed when doing redirects. 1782 Will always be in upper case.
2686 </remarks> 1783 </remarks>
1784 <see cref="P:HttpServer.IHttpRequest.Method"/>
2687 </member> 1785 </member>
2688 <member name="P:HttpServer.HttpResponse.Body"> 1786 <member name="P:HttpServer.IHttpRequest.Param">
2689 <summary>
2690 The body stream is used to cache the body contents
2691 before sending everything to the client. It's the simplest
2692 way to serve documents.
2693 </summary>
2694 </member>
2695 <member name="P:HttpServer.HttpResponse.Chunked">
2696 <summary>
2697 The chunked encoding modifies the body of a message in order to
2698 transfer it as a series of chunks, each with its own size indicator,
2699 followed by an OPTIONAL trailer containing entity-header fields. This
2700 allows dynamically produced content to be transferred along with the
2701 information necessary for the recipient to verify that it has
2702 received the full message.
2703 </summary>
2704 </member>
2705 <member name="P:HttpServer.HttpResponse.ProtocolVersion">
2706 <summary> 1787 <summary>
2707 Defines the version of the HTTP Response for applications where it's required 1788 Gets parameter from <see cref="P:HttpServer.IHttpRequest.QueryString"/> or <see cref="P:HttpServer.IHttpRequest.Form"/>.
2708 for this to be forced.
2709 </summary> 1789 </summary>
2710 </member> 1790 </member>
2711 <member name="P:HttpServer.HttpResponse.Connection"> 1791 <member name="P:HttpServer.IHttpRequest.QueryString">
2712 <summary> 1792 <summary>
2713 Kind of connection 1793 Gets variables sent in the query string
2714 </summary> 1794 </summary>
2715 </member> 1795 </member>
2716 <member name="P:HttpServer.HttpResponse.Encoding"> 1796 <member name="P:HttpServer.IHttpRequest.Uri">
2717 <summary> 1797 <summary>
2718 Encoding to use when sending stuff to the client. 1798 Gets or sets requested URI.
2719 </summary> 1799 </summary>
2720 <remarks>Default is UTF8</remarks>
2721 </member> 1800 </member>
2722 <member name="P:HttpServer.HttpResponse.KeepAlive"> 1801 <member name="P:HttpServer.IHttpRequest.UriParts">
2723 <summary> 1802 <summary>
2724 Number of seconds to keep connection alive 1803 Gets URI absolute path divided into parts.
2725 </summary> 1804 </summary>
2726 <remarks>Only used if Connection property is set to <see cref="F:HttpServer.ConnectionType.KeepAlive"/>.</remarks> 1805 <example>
1806 // URI is: http://gauffin.com/code/tiny/
1807 Console.WriteLine(request.UriParts[0]); // result: code
1808 Console.WriteLine(request.UriParts[1]); // result: tiny
1809 </example>
1810 <remarks>
1811 If you're using controllers than the first part is controller name,
1812 the second part is method name and the third part is Id property.
1813 </remarks>
1814 <seealso cref="P:HttpServer.IHttpRequest.Uri"/>
2727 </member> 1815 </member>
2728 <member name="P:HttpServer.HttpResponse.Status"> 1816 <member name="P:HttpServer.IHttpRequest.UriPath">
2729 <summary> 1817 <summary>
2730 Status code that is sent to the client. 1818 Gets or sets path and query.
2731 </summary> 1819 </summary>
2732 <remarks>Default is <see cref="F:System.Net.HttpStatusCode.OK"/></remarks> 1820 <see cref="P:HttpServer.IHttpRequest.Uri"/>
1821 <remarks>
1822 Are only used during request parsing. Cannot be set after "Host" header have been
1823 added.
1824 </remarks>
2733 </member> 1825 </member>
2734 <member name="P:HttpServer.HttpResponse.Reason"> 1826 <member name="T:HttpServer.Helpers.Implementations.PrototypeImp">
2735 <summary> 1827 <summary>
2736 Information about why a specific status code was used. 1828 PrototypeJS implementation of the javascript functions.
2737 </summary> 1829 </summary>
2738 </member> 1830 </member>
2739 <member name="P:HttpServer.HttpResponse.ContentLength"> 1831 <member name="T:HttpServer.Helpers.JavascriptHelperImplementation">
2740 <summary> 1832 <summary>
2741 Size of the body. MUST be specified before sending the header, 1833 Purpose of this class is to create a javascript toolkit independent javascript helper.
2742 unless property Chunked is set to true.
2743 </summary> 1834 </summary>
2744 </member> 1835 </member>
2745 <member name="P:HttpServer.HttpResponse.ContentType"> 1836 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.GenerateOptions(System.Text.StringBuilder,System.String[],System.Boolean)">
2746 <summary> 1837 <summary>
2747 Kind of content in the body 1838 Generates a list with JS options.
2748 </summary> 1839 </summary>
2749 <remarks>Default type is "text/html"</remarks> 1840 <param name="sb">StringBuilder that the options should be added to.</param>
1841 <param name="options">the javascript options. name, value pairs. each string value should be escaped by YOU!</param>
1842 <param name="startWithComma">true if we should start with a comma.</param>
2750 </member> 1843 </member>
2751 <member name="P:HttpServer.HttpResponse.HeadersSent"> 1844 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.RemoveJavascriptOptions(System.String[])">
2752 <summary> 1845 <summary>
2753 Headers have been sent to the client- 1846 Removes any javascript parameters from an array of parameters
2754 </summary> 1847 </summary>
2755 <remarks>You can not send any additional headers if they have already been sent.</remarks> 1848 <param name="options">The array of parameters to remove javascript params from</param>
1849 <returns>An array of html parameters</returns>
2756 </member> 1850 </member>
2757 <member name="P:HttpServer.HttpResponse.Sent"> 1851 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.AjaxFormOnSubmit(System.String[])">
2758 <summary> 1852 <summary>
2759 The whole response have been sent. 1853 javascript action that should be added to the "onsubmit" event in the form tag.
2760 </summary> 1854 </summary>
1855 <returns></returns>
1856 <remarks>All javascript option names should end with colon.</remarks>
1857 <example>
1858 <code>
1859 JSHelper.AjaxRequest("/user/show/1", "onsuccess:", "$('userInfo').update(result);");
1860 </code>
1861 </example>
2761 </member> 1862 </member>
2762 <member name="P:HttpServer.HttpResponse.Cookies"> 1863 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.AjaxRequest(System.String,System.String[])">
2763 <summary> 1864 <summary>
2764 Cookies that should be created/changed. 1865 Requests a url through ajax
2765 </summary> 1866 </summary>
1867 <param name="url">url to fetch</param>
1868 <param name="options">optional options in format "key, value, key, value", used in JS request object.</param>
1869 <returns>a link tag</returns>
1870 <remarks>All javascript option names should end with colon.</remarks>
1871 <example>
1872 <code>
1873 JSHelper.AjaxRequest("/user/show/1", "onsuccess:", "$('userInfo').update(result);");
1874 </code>
1875 </example>
2766 </member> 1876 </member>
2767 <member name="T:HttpServer.HttpInputItem"> 1877 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.AjaxUpdater(System.String,System.String,System.String[])">
2768 <summary> 1878 <summary>
2769 represents a HTTP input item. Each item can have multiple sub items, a sub item 1879 Ajax requests that updates an element with
2770 is made in a HTML form by using square brackets 1880 the fetched content
2771 </summary> 1881 </summary>
1882 <param name="url">Url to fetch content from</param>
1883 <param name="targetId">element to update</param>
1884 <param name="options">optional options in format "key, value, key, value", used in JS updater object.</param>
1885 <returns>A link tag.</returns>
1886 <remarks>All javascript option names should end with colon.</remarks>
2772 <example> 1887 <example>
2773 // <input type="text" name="user[FirstName]" value="jonas" /> becomes: 1888 <code>
2774 Console.WriteLine("Value: {0}", form["user"]["FirstName"].Value); 1889 JSHelper.AjaxUpdater("/user/show/1", "userInfo", "onsuccess:", "alert('Successful!');");
1890 </code>
2775 </example> 1891 </example>
2776 <remarks>
2777 All names in a form SHOULD be in lowercase.
2778 </remarks>
2779 </member> 1892 </member>
2780 <member name="F:HttpServer.HttpInputItem.Empty"> 1893 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.DialogLink(System.String,System.String,System.String[])">
2781 <summary> Representation of a non-initialized <see cref="T:HttpServer.HttpInputItem"/>.</summary>
2782 </member>
2783 <member name="M:HttpServer.HttpInputItem.#ctor(System.String,System.String)">
2784 <summary> 1894 <summary>
2785 Initializes an input item setting its name/identifier and value 1895 A link that pop ups a Dialog (overlay div)
2786 </summary> 1896 </summary>
2787 <param name="name">Parameter name/id</param> 1897 <param name="url">url to contents of dialog</param>
2788 <param name="value">Parameter value</param> 1898 <param name="title">link title</param>
2789 </member> 1899 <returns>A "a"-tag that popups a dialog when clicked</returns>
2790 <member name="M:HttpServer.HttpInputItem.#ctor(HttpServer.HttpInputItem)"> 1900 <param name="htmlAttributes">name/value of html attributes</param>
2791 <summary>Creates a deep copy of the item specified</summary> 1901 <example>
2792 <param name="item">The item to copy</param> 1902 WebHelper.DialogLink("/user/show/1", "show user", "onmouseover", "alert('booh!');");
2793 <remarks>The function makes a deep copy of quite a lot which can be slow</remarks> 1903 </example>
2794 </member> 1904 </member>
2795 <member name="M:HttpServer.HttpInputItem.Add(System.String)"> 1905 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.CloseDialog">
2796 <summary> 1906 <summary>
2797 Add another value to this item 1907 Close a javascript dialog window/div.
2798 </summary> 1908 </summary>
2799 <param name="value">Value to add.</param> 1909 <returns>javascript for closing a dialog.</returns>
2800 <exception cref="T:System.InvalidOperationException">Cannot add stuff to <see cref="F:HttpServer.HttpInput.Empty"/>.</exception> 1910 <see cref="M:HttpServer.Helpers.JavascriptHelperImplementation.DialogLink(System.String,System.String,System.String[])"/>
2801 </member> 1911 </member>
2802 <member name="M:HttpServer.HttpInputItem.Contains(System.String)"> 1912 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.CreateDialog(System.String,System.String,System.String[])">
2803 <summary> 1913 <summary>
2804 checks if a sub-item exists (and has a value). 1914 Creates a new modal dialog window
2805 </summary> 1915 </summary>
2806 <param name="name">name in lower case</param> 1916 <param name="url">url to open in window.</param>
2807 <returns>true if the sub-item exists and has a value; otherwise false.</returns> 1917 <param name="title">window title (may not be supported by all js implementations)</param>
2808 </member> 1918 <param name="options"></param>
2809 <member name="M:HttpServer.HttpInputItem.ToString"> 1919 <returns></returns>
2810 <summary> Returns a formatted representation of the instance with the values of all contained parameters </summary>
2811 </member> 1920 </member>
2812 <member name="M:HttpServer.HttpInputItem.ToString(System.String,System.Boolean)"> 1921 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.AjaxRequest(System.String,System.String[])">
2813 <summary> 1922 <summary>
2814 Outputs the string in a formatted manner 1923 Requests a url through ajax
2815 </summary> 1924 </summary>
2816 <param name="prefix">A prefix to append, used internally</param> 1925 <param name="url">url to fetch. Url is NOT enclosed in quotes by the implementation. You need to do that yourself.</param>
2817 <param name="asQuerySting">produce a query string</param> 1926 <param name="options">optional options in format "key, value, key, value", used in JS request object. All keys should end with colon.</param>
1927 <returns>a link tag</returns>
1928 <remarks>onclick attribute is used by this method.</remarks>
1929 <example>
1930 <code>
1931 // plain text
1932 JSHelper.AjaxRequest("'/user/show/1'");
1933
1934 // ajax request using this.href
1935 string link = "&lt;a href=\"/user/call/1\" onclick=\"" + JSHelper.AjaxRequest("this.href") + "/&lt;call user&lt;/a&gt;";
1936 </code>
1937 </example>
2818 </member> 1938 </member>
2819 <member name="M:HttpServer.HttpInputItem.Add(System.String,System.String)"> 1939 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.Contains(System.Collections.Generic.IEnumerable{System.String},System.String)">
2820 <summary> 1940 <summary>
2821 Add a sub item. 1941 Determins if a list of strings contains a specific value
2822 </summary> 1942 </summary>
2823 <param name="name">Can contain array formatting, the item is then parsed and added in multiple levels</param> 1943 <param name="options">options to check in</param>
2824 <param name="value">Value to add.</param> 1944 <param name="value">value to find</param>
2825 <exception cref="T:System.ArgumentNullException">Argument is null.</exception> 1945 <returns>true if value was found</returns>
2826 <exception cref="T:System.InvalidOperationException">Cannot add stuff to <see cref="F:HttpServer.HttpInput.Empty"/>.</exception> 1946 <remarks>case insensitive</remarks>
2827 </member> 1947 </member>
2828 <member name="M:HttpServer.HttpInputItem.System#Collections#Generic#IEnumerable{HttpServer#HttpInputItem}#GetEnumerator"> 1948 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.AjaxUpdater(System.String,System.String,System.String[])">
2829 <summary> 1949 <summary>
2830 Returns an enumerator that iterates through the collection. 1950 Ajax requests that updates an element with
1951 the fetched content
2831 </summary> 1952 </summary>
2832 1953 <param name="url">URL to fetch. URL is NOT enclosed in quotes by the implementation. You need to do that yourself.</param>
2833 <returns> 1954 <param name="targetId">element to update</param>
2834 A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> that can be used to iterate through the collection. 1955 <param name="options">options in format "key, value, key, value". All keys should end with colon.</param>
2835 </returns> 1956 <returns>A link tag.</returns>
2836 <filterpriority>1</filterpriority> 1957 <example>
1958 <code>
1959 JSHelper.AjaxUpdater("'/user/show/1'", "user", "onsuccess:", "alert('hello');", "asynchronous:", "true");
1960 </code>
1961 </example>
2837 </member> 1962 </member>
2838 <member name="M:HttpServer.HttpInputItem.GetEnumerator"> 1963 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.DialogLink(System.String,System.String,System.String[])">
2839 <summary> 1964 <summary>
2840 Returns an enumerator that iterates through a collection. 1965 A link that pop ups a Dialog (overlay div)
2841 </summary> 1966 </summary>
2842 1967 <param name="url">URL to contents of dialog</param>
1968 <param name="title">link title</param>
1969 <param name="htmlAttributes">name, value, name, value</param>
2843 <returns> 1970 <returns>
2844 An <see cref="T:System.Collections.IEnumerator"></see> object that can be used to iterate through the collection. 1971 A "a"-tag that popups a dialog when clicked
2845 </returns> 1972 </returns>
2846 <filterpriority>2</filterpriority> 1973 <remarks><para>Requires Control.Modal found here: http://livepipe.net/projects/control_modal/</para>
1974 And the following JavaScript (load it in application.js):
1975 <code>
1976 Event.observe(window, 'load',
1977 function() {
1978 document.getElementsByClassName('modal').each(function(link){ new Control.Modal(link); });
1979 }
1980 );
1981 </code>
1982 </remarks>
1983 <example>
1984 WebHelper.DialogLink("/user/show/1", "show user", "onmouseover", "alert('booh!');");
1985 </example>
2847 </member> 1986 </member>
2848 <member name="M:HttpServer.HttpInputItem.ToString(System.String)"> 1987 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.CreateDialog(System.String,System.String,System.String[])">
2849 <summary> 1988 <summary>
2850 Outputs the string in a formatted manner 1989 create a modal dialog (usually using DIVs)
2851 </summary> 1990 </summary>
2852 <param name="prefix">A prefix to append, used internally</param> 1991 <param name="url">url to fetch</param>
1992 <param name="title">dialog title</param>
1993 <param name="options">javascript/html attributes. javascript options ends with colon ':'.</param>
2853 <returns></returns> 1994 <returns></returns>
2854 </member> 1995 </member>
2855 <member name="P:HttpServer.HttpInputItem.Count"> 1996 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.CloseDialog">
2856 <summary>
2857 Number of values
2858 </summary>
2859 </member>
2860 <member name="P:HttpServer.HttpInputItem.Item(System.String)">
2861 <summary>
2862 Get a sub item
2863 </summary>
2864 <param name="name">name in lower case.</param>
2865 <returns><see cref="F:HttpServer.HttpInputItem.Empty"/> if no item was found.</returns>
2866 </member>
2867 <member name="P:HttpServer.HttpInputItem.Name">
2868 <summary>
2869 Name of item (in lower case).
2870 </summary>
2871 </member>
2872 <member name="P:HttpServer.HttpInputItem.Value">
2873 <summary>
2874 Returns the first value, or null if no value exist.
2875 </summary>
2876 </member>
2877 <member name="P:HttpServer.HttpInputItem.LastValue">
2878 <summary>
2879 Returns the last value, or null if no value exist.
2880 </summary>
2881 </member>
2882 <member name="P:HttpServer.HttpInputItem.Values">
2883 <summary> 1997 <summary>
2884 Returns the list with values. 1998 Close a javascript dialog window/div.
2885 </summary> 1999 </summary>
2000 <returns>javascript for closing a dialog.</returns>
2001 <see cref="M:HttpServer.Helpers.Implementations.PrototypeImp.DialogLink(System.String,System.String,System.String[])"/>
2886 </member> 2002 </member>
2887 <member name="P:HttpServer.HttpInputItem.HttpServer#IHttpInput#Item(System.String)"> 2003 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.AjaxFormOnSubmit(System.String[])">
2888 <summary> 2004 <summary>
2889 2005 javascript action that should be added to the "onsubmit" event in the form tag.
2890 </summary> 2006 </summary>
2891 <param name="name">name in lower case</param> 2007 <param name="options">remember to encapsulate strings in ''</param>
2892 <returns></returns> 2008 <returns></returns>
2009 <remarks>All javascript option names should end with colon.</remarks>
2010 <example>
2011 <code>
2012 JSHelper.AjaxRequest("/user/show/1", "onsuccess:", "$('userInfo').update(result);");
2013 </code>
2014 </example>
2893 </member> 2015 </member>
2894 <member name="T:HttpServer.Helpers.FormHelper"> 2016 <member name="T:HttpServer.Helpers.FormHelper">
2895 <summary> 2017 <summary>
@@ -3109,40 +2231,262 @@
3109 </summary> 2231 </summary>
3110 <returns></returns> 2232 <returns></returns>
3111 </member> 2233 </member>
3112 <member name="M:HttpServer.ComponentProvider.AddInstance``1(System.Object)"> 2234 <member name="T:HttpServer.ExceptionHandler">
3113 <summary> 2235 <summary>
3114 Add a component instance 2236 We dont want to let the server to die due to exceptions thrown in worker threads.
2237 therefore we use this delegate to give you a change to handle uncaught exceptions.
3115 </summary> 2238 </summary>
3116 <typeparam name="T">Interface type</typeparam> 2239 <param name="source">Class that the exception was thrown in.</param>
3117 <param name="instance">Instance to add</param> 2240 <param name="exception">Exception</param>
2241 <remarks>
2242 Server will throw a InternalServerException in release version if you dont
2243 handle this delegate.
2244 </remarks>
3118 </member> 2245 </member>
3119 <member name="M:HttpServer.ComponentProvider.Get``1"> 2246 <member name="T:HttpServer.Authentication.DigestAuthentication">
3120 <summary> 2247 <summary>
3121 Get a component. 2248 Implements HTTP Digest authentication. It's more secure than Basic auth since password is
2249 encrypted with a "key" from the server.
3122 </summary> 2250 </summary>
3123 <typeparam name="T">Interface type</typeparam>
3124 <returns>Component if registered, otherwise null.</returns>
3125 <remarks> 2251 <remarks>
3126 Component will get created if needed. 2252 Keep in mind that the password is encrypted with MD5. Use a combination of SSL and digest auth to be secure.
3127 </remarks> 2253 </remarks>
3128 </member> 2254 </member>
3129 <member name="M:HttpServer.ComponentProvider.Create(HttpServer.ComponentProvider.TypeInformation)"> 2255 <member name="T:HttpServer.Authentication.AuthenticationModule">
3130 <exception cref="T:System.InvalidOperationException">If instance cannot be created.</exception> 2256 <summary>
2257 Authentication modules are used to implement different
2258 kind of HTTP authentication.
2259 </summary>
3131 </member> 2260 </member>
3132 <member name="M:HttpServer.ComponentProvider.Contains(System.Type)"> 2261 <member name="F:HttpServer.Authentication.AuthenticationModule.AuthenticationTag">
3133 <summary> 2262 <summary>
3134 Checks if the specified component interface have been added. 2263 Tag used for authentication.
3135 </summary> 2264 </summary>
3136 <param name="interfaceType"></param>
3137 <returns>true if found; otherwise false.</returns>
3138 </member> 2265 </member>
3139 <member name="M:HttpServer.ComponentProvider.Add``2"> 2266 <member name="M:HttpServer.Authentication.AuthenticationModule.#ctor(HttpServer.Authentication.AuthenticationHandler,HttpServer.Authentication.AuthenticationRequiredHandler)">
3140 <summary> 2267 <summary>
3141 Add a component. 2268 Initializes a new instance of the <see cref="T:HttpServer.Authentication.AuthenticationModule"/> class.
3142 </summary> 2269 </summary>
3143 <typeparam name="InterfaceType">Type being requested.</typeparam> 2270 <param name="authenticator">Delegate used to provide information used during authentication.</param>
3144 <typeparam name="InstanceType">Type being created.</typeparam> 2271 <param name="authenticationRequiredHandler">Delegate used to determine if authentication is required (may be null).</param>
3145 <exception cref="T:System.InvalidOperationException">Type have already been mapped.</exception> 2272 </member>
2273 <member name="M:HttpServer.Authentication.AuthenticationModule.#ctor(HttpServer.Authentication.AuthenticationHandler)">
2274 <summary>
2275 Initializes a new instance of the <see cref="T:HttpServer.Authentication.AuthenticationModule"/> class.
2276 </summary>
2277 <param name="authenticator">Delegate used to provide information used during authentication.</param>
2278 </member>
2279 <member name="M:HttpServer.Authentication.AuthenticationModule.CreateResponse(System.String,System.Object[])">
2280 <summary>
2281 Create a response that can be sent in the WWW-Authenticate header.
2282 </summary>
2283 <param name="realm">Realm that the user should authenticate in</param>
2284 <param name="options">Array with optional options.</param>
2285 <returns>A correct authentication request.</returns>
2286 <exception cref="T:System.ArgumentNullException">If realm is empty or null.</exception>
2287 </member>
2288 <member name="M:HttpServer.Authentication.AuthenticationModule.Authenticate(System.String,System.String,System.String,System.Object[])">
2289 <summary>
2290 An authentication response have been received from the web browser.
2291 Check if it's correct
2292 </summary>
2293 <param name="authenticationHeader">Contents from the Authorization header</param>
2294 <param name="realm">Realm that should be authenticated</param>
2295 <param name="httpVerb">GET/POST/PUT/DELETE etc.</param>
2296 <param name="options">options to specific implementations</param>
2297 <returns>Authentication object that is stored for the request. A user class or something like that.</returns>
2298 <exception cref="T:System.ArgumentException">if <paramref name="authenticationHeader"/> is invalid</exception>
2299 <exception cref="T:System.ArgumentNullException">If any of the parameters is empty or null.</exception>
2300 </member>
2301 <member name="M:HttpServer.Authentication.AuthenticationModule.CheckAuthentication(System.String,System.String,System.String@,System.Object@)">
2302 <summary>
2303 Used to invoke the authentication delegate that is used to lookup the user name/realm.
2304 </summary>
2305 <param name="realm">Realm (domain) that user want to authenticate in</param>
2306 <param name="userName">User name</param>
2307 <param name="password">Password used for validation. Some implementations got password in clear text, they are then sent to client.</param>
2308 <param name="login">object that will be stored in the request to help you identify the user if authentication was successful.</param>
2309 <returns>true if authentication was successful</returns>
2310 </member>
2311 <member name="M:HttpServer.Authentication.AuthenticationModule.AuthenticationRequired(HttpServer.IHttpRequest)">
2312 <summary>
2313 Determines if authentication is required.
2314 </summary>
2315 <param name="request">HTTP request from browser</param>
2316 <returns>true if user should be authenticated.</returns>
2317 <remarks>throw <see cref="T:HttpServer.Exceptions.ForbiddenException"/> from your delegate if no more attempts are allowed.</remarks>
2318 <exception cref="T:HttpServer.Exceptions.ForbiddenException">If no more attempts are allowed</exception>
2319 </member>
2320 <member name="P:HttpServer.Authentication.AuthenticationModule.Name">
2321 <summary>
2322 name used in HTTP request.
2323 </summary>
2324 </member>
2325 <member name="M:HttpServer.Authentication.DigestAuthentication.#ctor(HttpServer.Authentication.AuthenticationHandler,HttpServer.Authentication.AuthenticationRequiredHandler)">
2326 <summary>
2327 Initializes a new instance of the <see cref="T:HttpServer.Authentication.DigestAuthentication"/> class.
2328 </summary>
2329 <param name="authenticator">Delegate used to provide information used during authentication.</param>
2330 <param name="authenticationRequiredHandler">Delegate used to determine if authentication is required (may be null).</param>
2331 </member>
2332 <member name="M:HttpServer.Authentication.DigestAuthentication.#ctor(HttpServer.Authentication.AuthenticationHandler)">
2333 <summary>
2334 Initializes a new instance of the <see cref="T:HttpServer.Authentication.DigestAuthentication"/> class.
2335 </summary>
2336 <param name="authenticator">Delegate used to provide information used during authentication.</param>
2337 </member>
2338 <member name="F:HttpServer.Authentication.DigestAuthentication.DisableNonceCheck">
2339 <summary>
2340 Used by test classes to be able to use hardcoded values
2341 </summary>
2342 </member>
2343 <member name="M:HttpServer.Authentication.DigestAuthentication.Authenticate(System.String,System.String,System.String,System.Object[])">
2344 <summary>
2345 An authentication response have been received from the web browser.
2346 Check if it's correct
2347 </summary>
2348 <param name="authenticationHeader">Contents from the Authorization header</param>
2349 <param name="realm">Realm that should be authenticated</param>
2350 <param name="httpVerb">GET/POST/PUT/DELETE etc.</param>
2351 <param name="options">First option: true if username/password is correct but not cnonce</param>
2352 <returns>
2353 Authentication object that is stored for the request. A user class or something like that.
2354 </returns>
2355 <exception cref="T:System.ArgumentException">if authenticationHeader is invalid</exception>
2356 <exception cref="T:System.ArgumentNullException">If any of the paramters is empty or null.</exception>
2357 </member>
2358 <member name="M:HttpServer.Authentication.DigestAuthentication.Encrypt(System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.String)">
2359 <summary>
2360 Encrypts parameters into a Digest string
2361 </summary>
2362 <param name="realm">Realm that the user want to log into.</param>
2363 <param name="userName">User logging in</param>
2364 <param name="password">Users password.</param>
2365 <param name="method">HTTP method.</param>
2366 <param name="uri">Uri/domain that generated the login prompt.</param>
2367 <param name="qop">Quality of Protection.</param>
2368 <param name="nonce">"Number used ONCE"</param>
2369 <param name="nc">Hexadecimal request counter.</param>
2370 <param name="cnonce">"Client Number used ONCE"</param>
2371 <returns>Digest encrypted string</returns>
2372 </member>
2373 <member name="M:HttpServer.Authentication.DigestAuthentication.Encrypt(System.String,System.String,System.String,System.String,System.String,System.String)">
2374 <summary>
2375
2376 </summary>
2377 <param name="ha1">Md5 hex encoded "userName:realm:password", without the quotes.</param>
2378 <param name="ha2">Md5 hex encoded "method:uri", without the quotes</param>
2379 <param name="qop">Quality of Protection</param>
2380 <param name="nonce">"Number used ONCE"</param>
2381 <param name="nc">Hexadecimal request counter.</param>
2382 <param name="cnonce">Client number used once</param>
2383 <returns></returns>
2384 </member>
2385 <member name="M:HttpServer.Authentication.DigestAuthentication.CreateResponse(System.String,System.Object[])">
2386 <summary>
2387 Create a response that can be sent in the WWW-Authenticate header.
2388 </summary>
2389 <param name="realm">Realm that the user should authenticate in</param>
2390 <param name="options">First options specifies if true if username/password is correct but not cnonce.</param>
2391 <returns>A correct auth request.</returns>
2392 <exception cref="T:System.ArgumentNullException">If realm is empty or null.</exception>
2393 </member>
2394 <member name="M:HttpServer.Authentication.DigestAuthentication.Decode(System.String,System.Text.Encoding)">
2395 <summary>
2396 Decodes authorization header value
2397 </summary>
2398 <param name="buffer">header value</param>
2399 <param name="encoding">Encoding that the buffer is in</param>
2400 <returns>All headers and their values if successful; otherwise null</returns>
2401 <example>
2402 NameValueCollection header = DigestAuthentication.Decode("response=\"6629fae49393a05397450978507c4ef1\",\r\nc=00001", Encoding.ASCII);
2403 </example>
2404 <remarks>Can handle lots of whitespaces and new lines without failing.</remarks>
2405 </member>
2406 <member name="M:HttpServer.Authentication.DigestAuthentication.GetCurrentNonce">
2407 <summary>
2408 Gets the current nonce.
2409 </summary>
2410 <returns></returns>
2411 </member>
2412 <member name="M:HttpServer.Authentication.DigestAuthentication.GetMD5HashBinHex2(System.String)">
2413 <summary>
2414 Gets the Md5 hash bin hex2.
2415 </summary>
2416 <param name="toBeHashed">To be hashed.</param>
2417 <returns></returns>
2418 </member>
2419 <member name="M:HttpServer.Authentication.DigestAuthentication.IsValidNonce(System.String)">
2420 <summary>
2421 determines if the nonce is valid or has expired.
2422 </summary>
2423 <param name="nonce">nonce value (check wikipedia for info)</param>
2424 <returns>true if the nonce has not expired.</returns>
2425 </member>
2426 <member name="P:HttpServer.Authentication.DigestAuthentication.Name">
2427 <summary>
2428 name used in http request.
2429 </summary>
2430 </member>
2431 <member name="P:HttpServer.Authentication.DigestAuthentication.TokenIsHA1">
2432 <summary>
2433 Gets or sets whether the token supplied in <see cref="T:HttpServer.Authentication.AuthenticationHandler"/> is a
2434 HA1 generated string.
2435 </summary>
2436 </member>
2437 <member name="T:HttpServer.HttpHelper">
2438 <summary>
2439 Generic helper functions for HTTP
2440 </summary>
2441 </member>
2442 <member name="F:HttpServer.HttpHelper.HTTP10">
2443 <summary>
2444 Version string for HTTP v1.0
2445 </summary>
2446 </member>
2447 <member name="F:HttpServer.HttpHelper.HTTP11">
2448 <summary>
2449 Version string for HTTP v1.1
2450 </summary>
2451 </member>
2452 <member name="F:HttpServer.HttpHelper.EmptyUri">
2453 <summary>
2454 An empty URI
2455 </summary>
2456 </member>
2457 <member name="M:HttpServer.HttpHelper.ParseQueryString(System.String)">
2458 <summary>
2459 Parses a query string.
2460 </summary>
2461 <param name="queryString">Query string (URI encoded)</param>
2462 <returns>A <see cref="T:HttpServer.HttpInput"/> object if successful; otherwise <see cref="F:HttpServer.HttpInput.Empty"/></returns>
2463 <exception cref="T:System.ArgumentNullException"><c>queryString</c> is null.</exception>
2464 <exception cref="T:System.FormatException">If string cannot be parsed.</exception>
2465 </member>
2466 <member name="T:HttpServer.Authentication.AuthenticationHandler">
2467 <summary>
2468 Delegate used to let authentication modules authenticate the user name and password.
2469 </summary>
2470 <param name="realm">Realm that the user want to authenticate in</param>
2471 <param name="userName">User name specified by client</param>
2472 <param name="token">Can either be user password or implementation specific token.</param>
2473 <param name="login">object that will be stored in a session variable called <see cref="F:HttpServer.Authentication.AuthenticationModule.AuthenticationTag"/> if authentication was successful.</param>
2474 <exception cref="T:HttpServer.Exceptions.ForbiddenException">throw forbidden exception if too many attempts have been made.</exception>
2475 <remarks>
2476 <para>
2477 Use <see cref="P:HttpServer.Authentication.DigestAuthentication.TokenIsHA1"/> to specify that the token is a HA1 token. (MD5 generated
2478 string from realm, user name and password); Md5String(userName + ":" + realm + ":" + password);
2479 </para>
2480 </remarks>
2481 </member>
2482 <member name="T:HttpServer.Authentication.AuthenticationRequiredHandler">
2483 <summary>
2484 Let's you decide on a system level if authentication is required.
2485 </summary>
2486 <param name="request">HTTP request from client</param>
2487 <returns>true if user should be authenticated.</returns>
2488 <remarks>throw <see cref="T:HttpServer.Exceptions.ForbiddenException"/> if no more attempts are allowed.</remarks>
2489 <exception cref="T:HttpServer.Exceptions.ForbiddenException">If no more attempts are allowed</exception>
3146 </member> 2490 </member>
3147 <member name="T:HttpServer.Parser.BodyEventArgs"> 2491 <member name="T:HttpServer.Parser.BodyEventArgs">
3148 <summary> 2492 <summary>
@@ -3177,6 +2521,284 @@
3177 Gets or sets offset in buffer where to start processing. 2521 Gets or sets offset in buffer where to start processing.
3178 </summary> 2522 </summary>
3179 </member> 2523 </member>
2524 <member name="T:HttpServer.Method">
2525 <summary>
2526 Contains all HTTP Methods (according to the HTTP 1.1 specification)
2527 <para>
2528 See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
2529 </para>
2530 </summary>
2531 </member>
2532 <member name="F:HttpServer.Method.Delete">
2533 <summary>
2534 The DELETE method requests that the origin server delete the resource identified by the Request-URI.
2535 </summary>
2536 <remarks>
2537 <para>
2538 This method MAY be overridden by human intervention (or other means) on the origin server.
2539 The client cannot be guaranteed that the operation has been carried out, even if the status code
2540 returned from the origin server indicates that the action has been completed successfully.
2541 </para>
2542 <para>
2543 However, the server SHOULD NOT indicate success unless, at the time the response is given,
2544 it intends to delete the resource or move it to an inaccessible location.
2545 </para>
2546 <para>
2547 A successful response SHOULD be 200 (OK) if the response includes an entity describing the status,
2548 202 (Accepted) if the action has not yet been enacted,
2549 or 204 (No Content) if the action has been enacted but the response does not include an entity.
2550 </para>
2551 <para>
2552 If the request passes through a cache and the Request-URI identifies one or more currently cached entities,
2553 those entries SHOULD be treated as stale. Responses to this method are not cacheable.
2554 </para>
2555 </remarks>
2556 </member>
2557 <member name="F:HttpServer.Method.Get">
2558 <summary>
2559 The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.
2560 </summary>
2561 <remarks>
2562 <para>
2563 If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the
2564 entity in the response and not the source text of the process, unless that text happens to be the output of the process.
2565 </para>
2566 <para>
2567 The semantics of the GET method change to a "conditional GET" if the request message includes an
2568 If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field.
2569 A conditional GET method requests that the entity be transferred only under the circumstances described
2570 by the conditional header field(s). The conditional GET method is intended to reduce unnecessary network
2571 usage by allowing cached entities to be refreshed without requiring multiple requests or transferring
2572 data already held by the client.
2573 </para>
2574 </remarks>
2575 </member>
2576 <member name="F:HttpServer.Method.Header">
2577 <summary>
2578 The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response.
2579 </summary>
2580 <remarks>
2581 The meta information contained in the HTTP headers in response to a HEAD request SHOULD be identical to the
2582 information sent in response to a GET request. This method can be used for obtaining meta information about
2583 the entity implied by the request without transferring the entity-body itself.
2584
2585 This method is often used for testing hypertext links for validity, accessibility, and recent modification.
2586 </remarks>
2587 </member>
2588 <member name="F:HttpServer.Method.Options">
2589 <summary>
2590 <para>The OPTIONS method represents a request for information about the communication options available on the request/response chain identified by the Request-URI.</para>
2591 </summary>
2592 <remarks>
2593 <para>This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.</para>
2594 </remarks>
2595 </member>
2596 <member name="F:HttpServer.Method.Post">
2597 <summary>
2598 The POST method is used to request that the origin server accept the entity enclosed
2599 in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.
2600 </summary>
2601 <remarks>
2602 POST is designed to allow a uniform method to cover the following functions:
2603 <list type="bullet">
2604 <item>
2605 Annotation of existing resources;
2606 </item><item>
2607 Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
2608 </item><item>
2609 Providing a block of data, such as the result of submitting a form, to a data-handling process;
2610 </item><item>
2611 Extending a database through an append operation.
2612 </item>
2613 </list>
2614 <para>
2615 If a resource has been created on the origin server, the response SHOULD be 201 (Created) and
2616 contain an entity which describes the status of the request and refers to the new resource, and a
2617 Location header (see section 14.30).
2618 </para>
2619 <para>
2620 The action performed by the POST method might not result in a resource that can be identified by a URI.
2621 In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on
2622 whether or not the response includes an entity that describes the result.
2623 </para><para>
2624 Responses to this method are not cacheable, unless the response includes appropriate Cache-Control
2625 or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent
2626 to retrieve a cacheable resource.
2627 </para>
2628 </remarks>
2629 </member>
2630 <member name="F:HttpServer.Method.Put">
2631 <summary>
2632 The PUT method requests that the enclosed entity be stored under the supplied Request-URI.
2633 </summary>
2634 <remarks>
2635 <list type="bullet">
2636 <item>
2637 If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a
2638 modified version of the one residing on the origin server.
2639 </item><item>
2640 If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new
2641 resource by the requesting user agent, the origin server can create the resource with that URI.
2642 </item><item>
2643 If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response.
2644 </item><item>
2645 If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to
2646 indicate successful completion of the request.
2647 </item><item>
2648 If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be
2649 given that reflects the nature of the problem.
2650 </item>
2651 </list>
2652 <para>
2653 The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not
2654 understand or implement and MUST return a 501 (Not Implemented) response in such cases.
2655 </para>
2656 </remarks>
2657 </member>
2658 <member name="F:HttpServer.Method.Trace">
2659 <summary>
2660 The TRACE method is used to invoke a remote, application-layer loop- back of the request message.
2661 </summary>
2662 </member>
2663 <member name="T:HttpServer.Methods">
2664 <summary>
2665 Contains all HTTP Methods (according to the HTTP 1.1 specification)
2666 <para>
2667 See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
2668 </para>
2669 </summary>
2670 </member>
2671 <member name="F:HttpServer.Methods.Delete">
2672 <summary>
2673 The DELETE method requests that the origin server delete the resource identified by the Request-URI.
2674 </summary>
2675 <remarks>
2676 <para>
2677 This method MAY be overridden by human intervention (or other means) on the origin server.
2678 The client cannot be guaranteed that the operation has been carried out, even if the status code
2679 returned from the origin server indicates that the action has been completed successfully.
2680 </para>
2681 <para>
2682 However, the server SHOULD NOT indicate success unless, at the time the response is given,
2683 it intends to delete the resource or move it to an inaccessible location.
2684 </para>
2685 <para>
2686 A successful response SHOULD be 200 (OK) if the response includes an entity describing the status,
2687 202 (Accepted) if the action has not yet been enacted,
2688 or 204 (No Content) if the action has been enacted but the response does not include an entity.
2689 </para>
2690 <para>
2691 If the request passes through a cache and the Request-URI identifies one or more currently cached entities,
2692 those entries SHOULD be treated as stale. Responses to this method are not cacheable.
2693 </para>
2694 </remarks>
2695 </member>
2696 <member name="F:HttpServer.Methods.Get">
2697 <summary>
2698 The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.
2699 </summary>
2700 <remarks>
2701 <para>
2702 If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the
2703 entity in the response and not the source text of the process, unless that text happens to be the output of the process.
2704 </para>
2705 <para>
2706 The semantics of the GET method change to a "conditional GET" if the request message includes an
2707 If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field.
2708 A conditional GET method requests that the entity be transferred only under the circumstances described
2709 by the conditional header field(s). The conditional GET method is intended to reduce unnecessary network
2710 usage by allowing cached entities to be refreshed without requiring multiple requests or transferring
2711 data already held by the client.
2712 </para>
2713 </remarks>
2714 </member>
2715 <member name="F:HttpServer.Methods.Header">
2716 <summary>
2717 The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response.
2718 </summary>
2719 <remarks>
2720 The meta information contained in the HTTP headers in response to a HEAD request SHOULD be identical to the
2721 information sent in response to a GET request. This method can be used for obtaining meta information about
2722 the entity implied by the request without transferring the entity-body itself.
2723
2724 This method is often used for testing hypertext links for validity, accessibility, and recent modification.
2725 </remarks>
2726 </member>
2727 <member name="F:HttpServer.Methods.Options">
2728 <summary>
2729 <para>The OPTIONS method represents a request for information about the communication options available on the request/response chain identified by the Request-URI.</para>
2730 </summary>
2731 <remarks>
2732 <para>This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.</para>
2733 </remarks>
2734 </member>
2735 <member name="F:HttpServer.Methods.Post">
2736 <summary>
2737 The POST method is used to request that the origin server accept the entity enclosed
2738 in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.
2739 </summary>
2740 <remarks>
2741 POST is designed to allow a uniform method to cover the following functions:
2742 <list type="bullet">
2743 <item>
2744 Annotation of existing resources;
2745 </item><item>
2746 Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
2747 </item><item>
2748 Providing a block of data, such as the result of submitting a form, to a data-handling process;
2749 </item><item>
2750 Extending a database through an append operation.
2751 </item>
2752 </list>
2753 <para>
2754 If a resource has been created on the origin server, the response SHOULD be 201 (Created) and
2755 contain an entity which describes the status of the request and refers to the new resource, and a
2756 Location header (see section 14.30).
2757 </para>
2758 <para>
2759 The action performed by the POST method might not result in a resource that can be identified by a URI.
2760 In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on
2761 whether or not the response includes an entity that describes the result.
2762 </para><para>
2763 Responses to this method are not cacheable, unless the response includes appropriate Cache-Control
2764 or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent
2765 to retrieve a cacheable resource.
2766 </para>
2767 </remarks>
2768 </member>
2769 <member name="F:HttpServer.Methods.Put">
2770 <summary>
2771 The PUT method requests that the enclosed entity be stored under the supplied Request-URI.
2772 </summary>
2773 <remarks>
2774 <list type="bullet">
2775 <item>
2776 If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a
2777 modified version of the one residing on the origin server.
2778 </item><item>
2779 If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new
2780 resource by the requesting user agent, the origin server can create the resource with that URI.
2781 </item><item>
2782 If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response.
2783 </item><item>
2784 If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to
2785 indicate successful completion of the request.
2786 </item><item>
2787 If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be
2788 given that reflects the nature of the problem.
2789 </item>
2790 </list>
2791 <para>
2792 The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not
2793 understand or implement and MUST return a 501 (Not Implemented) response in such cases.
2794 </para>
2795 </remarks>
2796 </member>
2797 <member name="F:HttpServer.Methods.Trace">
2798 <summary>
2799 The TRACE method is used to invoke a remote, application-layer loop- back of the request message.
2800 </summary>
2801 </member>
3180 <member name="T:HttpServer.HttpContextFactory"> 2802 <member name="T:HttpServer.HttpContextFactory">
3181 <summary> 2803 <summary>
3182 Used to create and reuse contexts. 2804 Used to create and reuse contexts.
@@ -3364,178 +2986,247 @@
3364 </summary> 2986 </summary>
3365 <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> 2987 <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
3366 </member> 2988 </member>
3367 <member name="T:HttpServer.HttpModules.ResourceFileModule"> 2989 <member name="T:HttpServer.ClientAcceptedEventArgs">
3368 <summary> 2990 <summary>
3369 Serves files that are stored in embedded resources. 2991 Invoked when a client have been accepted by the <see cref="T:HttpServer.HttpListener"/>
3370 </summary> 2992 </summary>
2993 <remarks>
2994 Can be used to revoke incoming connections
2995 </remarks>
3371 </member> 2996 </member>
3372 <member name="T:HttpServer.HttpModules.HttpModule"> 2997 <member name="M:HttpServer.ClientAcceptedEventArgs.#ctor(System.Net.Sockets.Socket)">
3373 <summary> 2998 <summary>
3374 A HttpModule can be used to serve Uri's. The module itself 2999 Initializes a new instance of the <see cref="T:HttpServer.ClientAcceptedEventArgs"/> class.
3375 decides if it should serve a Uri or not. In this way, you can
3376 get a very flexible http application since you can let multiple modules
3377 serve almost similar urls.
3378 </summary> 3000 </summary>
3379 <remarks> 3001 <param name="socket">The socket.</param>
3380 Throw <see cref="T:HttpServer.Exceptions.UnauthorizedException"/> if you are using a <see cref="T:HttpServer.Authentication.AuthenticationModule"/> and want to prompt for user name/password.
3381 </remarks>
3382 </member> 3002 </member>
3383 <member name="M:HttpServer.HttpModules.HttpModule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)"> 3003 <member name="M:HttpServer.ClientAcceptedEventArgs.Revoke">
3384 <summary> 3004 <summary>
3385 Method that process the url 3005 Client may not be handled.
3386 </summary> 3006 </summary>
3387 <param name="request">Information sent by the browser about the request</param>
3388 <param name="response">Information that is being sent back to the client.</param>
3389 <param name="session">Session used to </param>
3390 <returns>true if this module handled the request.</returns>
3391 </member> 3007 </member>
3392 <member name="M:HttpServer.HttpModules.HttpModule.SetLogWriter(HttpServer.ILogWriter)"> 3008 <member name="P:HttpServer.ClientAcceptedEventArgs.Socket">
3393 <summary> 3009 <summary>
3394 Set the log writer to use. 3010 Accepted socket.
3395 </summary> 3011 </summary>
3396 <param name="writer">logwriter to use.</param>
3397 </member> 3012 </member>
3398 <member name="M:HttpServer.HttpModules.HttpModule.Write(HttpServer.LogPrio,System.String)"> 3013 <member name="P:HttpServer.ClientAcceptedEventArgs.Revoked">
3399 <summary> 3014 <summary>
3400 Log something. 3015 Client should be revoked.
3401 </summary> 3016 </summary>
3402 <param name="prio">importance of log message</param>
3403 <param name="message">message</param>
3404 </member> 3017 </member>
3405 <member name="P:HttpServer.HttpModules.HttpModule.AllowSecondaryProcessing"> 3018 <member name="T:HttpServer.Sessions.MemorySession">
3406 <summary> 3019 <summary>
3407 If true specifies that the module doesn't consume the processing of a request so that subsequent modules 3020 A session stored in memory.
3408 can continue processing afterwards. Default is false.
3409 </summary> 3021 </summary>
3410 </member> 3022 </member>
3411 <member name="M:HttpServer.HttpModules.ResourceFileModule.#ctor"> 3023 <member name="T:HttpServer.Sessions.IHttpSession">
3412 <summary> 3024 <summary>
3413 Initializes a new instance of the <see cref="T:HttpServer.HttpModules.ResourceFileModule"/> class. 3025 Interface for sessions
3414 Runs <see cref="M:HttpServer.HttpModules.ResourceFileModule.AddDefaultMimeTypes"/> to make sure the basic mime types are available, they can be cleared later
3415 through the use of <see cref="P:HttpServer.HttpModules.ResourceFileModule.MimeTypes"/> if desired.
3416 </summary> 3026 </summary>
3417 </member> 3027 </member>
3418 <member name="M:HttpServer.HttpModules.ResourceFileModule.#ctor(HttpServer.ILogWriter)"> 3028 <member name="M:HttpServer.Sessions.IHttpSession.Clear">
3419 <summary> 3029 <summary>
3420 Initializes a new instance of the <see cref="T:HttpServer.HttpModules.ResourceFileModule"/> class. 3030 Remove everything from the session
3421 Runs <see cref="M:HttpServer.HttpModules.ResourceFileModule.AddDefaultMimeTypes"/> to make sure the basic mime types are available, they can be cleared later
3422 through the use of <see cref="P:HttpServer.HttpModules.ResourceFileModule.MimeTypes"/> if desired.
3423 </summary> 3031 </summary>
3424 <param name="logWriter">The log writer to use when logging events</param>
3425 </member> 3032 </member>
3426 <member name="M:HttpServer.HttpModules.ResourceFileModule.AddDefaultMimeTypes"> 3033 <member name="M:HttpServer.Sessions.IHttpSession.Clear(System.Boolean)">
3427 <summary> 3034 <summary>
3428 Mimtypes that this class can handle per default 3035 Remove everything from the session
3429 </summary> 3036 </summary>
3037 <param name="expires">True if the session is cleared due to expiration</param>
3430 </member> 3038 </member>
3431 <member name="M:HttpServer.HttpModules.ResourceFileModule.AddResources(System.String,System.Reflection.Assembly,System.String)"> 3039 <member name="P:HttpServer.Sessions.IHttpSession.Id">
3432 <summary> 3040 <summary>
3433 Loads resources from a namespace in the given assembly to an uri 3041 Session id
3434 </summary> 3042 </summary>
3435 <param name="toUri">The uri to map the resources to</param> 3043 </member>
3436 <param name="fromAssembly">The assembly in which the resources reside</param> 3044 <member name="P:HttpServer.Sessions.IHttpSession.Item(System.String)">
3437 <param name="fromNamespace">The namespace from which to load the resources</param> 3045 <summary>
3438 <usage> 3046 Should
3439 resourceLoader.LoadResources("/user/", typeof(User).Assembly, "MyLib.Models.User.Views"); 3047 </summary>
3048 <param name="name">Name of the session variable</param>
3049 <returns>null if it's not set</returns>
3050 <exception cref="T:System.Runtime.Serialization.SerializationException">If the object cant be serialized.</exception>
3051 </member>
3052 <member name="P:HttpServer.Sessions.IHttpSession.Accessed">
3053 <summary>
3054 When the session was last accessed.
3055 This property is touched by the http server each time the
3056 session is requested.
3057 </summary>
3058 </member>
3059 <member name="P:HttpServer.Sessions.IHttpSession.Count">
3060 <summary>
3061 Number of session variables.
3062 </summary>
3063 </member>
3064 <member name="E:HttpServer.Sessions.IHttpSession.BeforeClear">
3065 <summary>
3066 Event triggered upon clearing the session
3067 </summary>
3068 </member>
3069 <member name="M:HttpServer.Sessions.MemorySession.#ctor(System.String)">
3070 <summary>
3440 3071
3441 will make ie the resource MyLib.Models.User.Views.stylesheet.css accessible via /user/stylesheet.css 3072 </summary>
3442 </usage> 3073 <param name="id">A unique id used by the sessions store to identify the session</param>
3443 <returns>The amount of loaded files, giving you the possibility of making sure the resources needed gets loaded</returns>
3444 </member> 3074 </member>
3445 <member name="M:HttpServer.HttpModules.ResourceFileModule.CanHandle(HttpServer.IHttpRequest)"> 3075 <member name="M:HttpServer.Sessions.MemorySession.SetId(System.String)">
3446 <summary> 3076 <summary>
3447 Returns true if the module can handle the request 3077 Id
3448 </summary> 3078 </summary>
3079 <param name="id"></param>
3449 </member> 3080 </member>
3450 <member name="M:HttpServer.HttpModules.ResourceFileModule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)"> 3081 <member name="M:HttpServer.Sessions.MemorySession.Clear">
3451 <summary> 3082 <summary>
3452 Method that process the url 3083 Remove everything from the session
3453 </summary> 3084 </summary>
3454 <param name="request">Information sent by the browser about the request</param>
3455 <param name="response">Information that is being sent back to the client.</param>
3456 <param name="session">Session used to </param>
3457 <returns>true if this module handled the request.</returns>
3458 </member> 3085 </member>
3459 <member name="P:HttpServer.HttpModules.ResourceFileModule.MimeTypes"> 3086 <member name="M:HttpServer.Sessions.MemorySession.Clear(System.Boolean)">
3460 <summary> 3087 <summary>
3461 List with all mime-type that are allowed. 3088 Clears the specified expire.
3462 </summary> 3089 </summary>
3463 <remarks>All other mime types will result in a Forbidden http status code.</remarks> 3090 <param name="expires">True if the session is cleared due to expiration</param>
3464 </member> 3091 </member>
3465 <member name="T:HttpServer.HttpModules.FileModule"> 3092 <member name="M:HttpServer.Sessions.MemorySession.Dispose">
3466 <summary> 3093 <summary>
3467 The purpose of this module is to serve files. 3094 Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
3468 </summary> 3095 </summary>
3096 <filterpriority>2</filterpriority>
3469 </member> 3097 </member>
3470 <member name="M:HttpServer.HttpModules.FileModule.#ctor(System.String,System.String,System.Boolean)"> 3098 <member name="P:HttpServer.Sessions.MemorySession.Id">
3471 <summary> 3099 <summary>
3472 Initializes a new instance of the <see cref="T:HttpServer.HttpModules.FileModule"/> class. 3100 Session id
3473 </summary> 3101 </summary>
3474 <param name="baseUri">Uri to serve, for instance "/files/"</param>
3475 <param name="basePath">Path on hard drive where we should start looking for files</param>
3476 <param name="useLastModifiedHeader">If true a Last-Modifed header will be sent upon requests urging web browser to cache files</param>
3477 </member> 3102 </member>
3478 <member name="M:HttpServer.HttpModules.FileModule.#ctor(System.String,System.String)"> 3103 <member name="P:HttpServer.Sessions.MemorySession.Item(System.String)">
3479 <summary> 3104 <summary>
3480 Initializes a new instance of the <see cref="T:HttpServer.HttpModules.FileModule"/> class. 3105 Should
3481 </summary> 3106 </summary>
3482 <param name="baseUri">Uri to serve, for instance "/files/"</param> 3107 <param name="name">Name of the session variable</param>
3483 <param name="basePath">Path on hard drive where we should start looking for files</param> 3108 <returns>null if it's not set</returns>
3484 </member> 3109 </member>
3485 <member name="M:HttpServer.HttpModules.FileModule.AddDefaultMimeTypes"> 3110 <member name="P:HttpServer.Sessions.MemorySession.Accessed">
3486 <summary> 3111 <summary>
3487 Mimtypes that this class can handle per default 3112 when the session was last accessed.
3488 </summary> 3113 </summary>
3114 <remarks>
3115 Used to determine when the session should be removed.
3116 </remarks>
3489 </member> 3117 </member>
3490 <member name="M:HttpServer.HttpModules.FileModule.CanHandle(System.Uri)"> 3118 <member name="P:HttpServer.Sessions.MemorySession.Count">
3491 <summary> 3119 <summary>
3492 Determines if the request should be handled by this module. 3120 Number of values in the session
3493 Invoked by the <see cref="T:HttpServer.HttpServer"/>
3494 </summary> 3121 </summary>
3495 <param name="uri"></param>
3496 <returns>true if this module should handle it.</returns>
3497 </member> 3122 </member>
3498 <member name="M:HttpServer.HttpModules.FileModule.GetPath(System.Uri)"> 3123 <member name="P:HttpServer.Sessions.MemorySession.Changed">
3499 <exception cref="T:HttpServer.Exceptions.BadRequestException">Illegal path</exception> 3124 <summary>
3125 Flag to indicate that the session have been changed
3126 and should be saved into the session store.
3127 </summary>
3500 </member> 3128 </member>
3501 <member name="M:HttpServer.HttpModules.FileModule.Contains(System.String,System.Collections.Generic.IEnumerable{System.String})"> 3129 <member name="E:HttpServer.Sessions.MemorySession.BeforeClear">
3502 <summary> 3130 <summary>
3503 check if source contains any of the chars. 3131 Event triggered upon clearing the session
3504 </summary> 3132 </summary>
3505 <param name="source"></param>
3506 <param name="chars"></param>
3507 <returns></returns>
3508 </member> 3133 </member>
3509 <member name="M:HttpServer.HttpModules.FileModule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)"> 3134 <member name="T:HttpServer.HttpModules.ReverseProxyModule">
3510 <summary> 3135 <summary>
3511 Method that process the Uri. 3136 A reverse proxy are used to act as a bridge between local (protected/hidden) websites
3137 and public clients.
3138
3139 A typical usage is to allow web servers on non standard ports to still be available
3140 to the public clients, or allow web servers on private ips to be available.
3141 </summary>
3142 </member>
3143 <member name="M:HttpServer.HttpModules.ReverseProxyModule.#ctor(System.String,System.String)">
3144 <summary>
3145
3146 </summary>
3147 <param name="source">Base url requested from browser</param>
3148 <param name="destination">Base url on private web server</param>
3149 <example>
3150 // this will return contents from http://192.168.1.128/view/jonas when client requests http://www.gauffin.com/user/view/jonas
3151 _server.Add(new ReverseProxyModule("http://www.gauffin.com/user/", "http://192.168.1.128/");
3152 </example>
3153 </member>
3154 <member name="M:HttpServer.HttpModules.ReverseProxyModule.CanHandle(System.Uri)">
3155 <summary>
3156 Method that determines if an url should be handled or not by the module
3157 </summary>
3158 <param name="uri">Url requested by the client.</param>
3159 <returns>true if module should handle the url.</returns>
3160 </member>
3161 <member name="M:HttpServer.HttpModules.ReverseProxyModule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)">
3162 <summary>
3163 Method that process the url
3512 </summary> 3164 </summary>
3513 <param name="request">Information sent by the browser about the request</param> 3165 <param name="request">Information sent by the browser about the request</param>
3514 <param name="response">Information that is being sent back to the client.</param> 3166 <param name="response">Information that is being sent back to the client.</param>
3515 <param name="session">Session used to </param> 3167 <param name="session">Session used to </param>
3516 <exception cref="T:HttpServer.Exceptions.InternalServerException">Failed to find file extension</exception>
3517 <exception cref="T:HttpServer.Exceptions.ForbiddenException">File type is forbidden.</exception>
3518 </member> 3168 </member>
3519 <member name="M:HttpServer.HttpModules.FileModule.GetFileExtension(System.String)"> 3169 <member name="T:HttpServer.FormDecoders.UrlDecoder">
3520 <summary> 3170 <summary>
3521 return a file extension from an absolute Uri path (or plain filename) 3171 Can handle application/x-www-form-urlencoded
3522 </summary> 3172 </summary>
3523 <param name="uri"></param>
3524 <returns></returns>
3525 </member> 3173 </member>
3526 <member name="P:HttpServer.HttpModules.FileModule.MimeTypes"> 3174 <member name="M:HttpServer.FormDecoders.UrlDecoder.Decode(System.IO.Stream,System.String,System.Text.Encoding)">
3527 <summary> 3175 <summary>
3528 List with all mime-type that are allowed.
3529 </summary> 3176 </summary>
3530 <remarks>All other mime types will result in a Forbidden http status code.</remarks> 3177 <param name="stream">Stream containing the content</param>
3178 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case</param>
3179 <param name="encoding">Stream encoding</param>
3180 <returns>
3181 A HTTP form, or null if content could not be parsed.
3182 </returns>
3183 <exception cref="T:System.IO.InvalidDataException">If contents in the stream is not valid input data.</exception>
3531 </member> 3184 </member>
3532 <member name="P:HttpServer.HttpModules.FileModule.ForbiddenChars"> 3185 <member name="M:HttpServer.FormDecoders.UrlDecoder.CanParse(System.String)">
3533 <summary> 3186 <summary>
3534 characters that may not exist in a path. 3187 Checks if the decoder can handle the mime type
3188 </summary>
3189 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case.</param>
3190 <returns>True if the decoder can parse the specified content type</returns>
3191 </member>
3192 <member name="T:HttpServer.FormDecoders.FormDecoderProvider">
3193 <summary>
3194 This provider is used to let us implement any type of form decoding we want without
3195 having to rewrite anything else in the server.
3196 </summary>
3197 </member>
3198 <member name="M:HttpServer.FormDecoders.FormDecoderProvider.Decode(System.String,System.IO.Stream,System.Text.Encoding)">
3199 <summary>
3200
3201 </summary>
3202 <param name="contentType">Should contain boundary and type, as in: multipart/form-data; boundary=---------------------------230051238959</param>
3203 <param name="stream">Stream containing form data.</param>
3204 <param name="encoding">Encoding used when decoding the stream</param>
3205 <returns><see cref="F:HttpServer.HttpInput.Empty"/> if no parser was found.</returns>
3206 <exception cref="T:System.ArgumentException">If stream is null or not readable.</exception>
3207 <exception cref="T:System.IO.InvalidDataException">If stream contents cannot be decoded properly.</exception>
3208 </member>
3209 <member name="M:HttpServer.FormDecoders.FormDecoderProvider.Add(HttpServer.FormDecoders.IFormDecoder)">
3210 <summary>
3211 Add a decoder.
3212 </summary>
3213 <param name="decoder"></param>
3214 <exception cref="T:System.ArgumentNullException"></exception>
3215 </member>
3216 <member name="P:HttpServer.FormDecoders.FormDecoderProvider.Count">
3217 <summary>
3218 Number of added decoders.
3219 </summary>
3220 </member>
3221 <member name="P:HttpServer.FormDecoders.FormDecoderProvider.Decoders">
3222 <summary>
3223 Use with care.
3224 </summary>
3225 </member>
3226 <member name="P:HttpServer.FormDecoders.FormDecoderProvider.DefaultDecoder">
3227 <summary>
3228 Decoder used for unknown content types.
3535 </summary> 3229 </summary>
3536 <example>
3537 fileMod.ForbiddenChars = new string[]{ "\\", "..", ":" };
3538 </example>
3539 </member> 3230 </member>
3540 <member name="T:HttpServer.Exceptions.InternalServerException"> 3231 <member name="T:HttpServer.Exceptions.InternalServerException">
3541 <summary> 3232 <summary>
@@ -3560,73 +3251,425 @@
3560 <param name="message">error message.</param> 3251 <param name="message">error message.</param>
3561 <param name="inner">inner exception.</param> 3252 <param name="inner">inner exception.</param>
3562 </member> 3253 </member>
3563 <member name="T:HttpServer.Rules.RegexRedirectRule"> 3254 <member name="T:HttpServer.IHttpResponse">
3564 <summary> 3255 <summary>
3565 Class to make dynamic binding of redirects. Instead of having to specify a number of similar redirect rules 3256 Response that is sent back to the web browser / client.
3566 a regular expression can be used to identify redirect URLs and their targets. 3257
3258 A response can be sent if different ways. The easiest one is
3259 to just fill the Body stream with content, everything else
3260 will then be taken care of by the framework. The default content-type
3261 is text/html, you should change it if you send anything else.
3262
3263 The second and slighty more complex way is to send the response
3264 as parts. Start with sending the header using the SendHeaders method and
3265 then you can send the body using SendBody method, but do not forget
3266 to set ContentType and ContentLength before doing so.
3567 </summary> 3267 </summary>
3568 <example> 3268 <example>
3569 <![CDATA[ 3269 public void MyHandler(IHttpRequest request, IHttpResponse response)
3570 new RegexRedirectRule("/(?<target>[a-z0-9]+)", "/users/${target}?find=true", RegexOptions.IgnoreCase) 3270 {
3571 ]]> 3271
3272 }
3572 </example> 3273 </example>
3573 </member> 3274 </member>
3574 <member name="M:HttpServer.Rules.RegexRedirectRule.#ctor(System.String,System.String)"> 3275 <member name="M:HttpServer.IHttpResponse.AddHeader(System.String,System.String)">
3575 <summary> 3276 <summary>
3576 Initializes a new instance of the <see cref="T:HttpServer.Rules.RegexRedirectRule"/> class. 3277 Add another header to the document.
3577 </summary> 3278 </summary>
3578 <param name="fromUrlExpression">Expression to match URL</param> 3279 <param name="name">Name of the header, case sensitive, use lower cases.</param>
3579 <param name="toUrlExpression">Expression to generate URL</param> 3280 <param name="value">Header values can span over multiple lines as long as each line starts with a white space. New line chars should be \r\n</param>
3580 <example> 3281 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
3581 <![CDATA[ 3282 <exception cref="T:System.ArgumentException">If value conditions have not been met.</exception>
3582 server.Add(new RegexRedirectRule("/(?<first>[a-zA-Z0-9]+)", "/user/${first}")); 3283 <remarks>Adding any header will override the default ones and those specified by properties.</remarks>
3583 Result of ie. /employee1 will then be /user/employee1
3584 ]]>
3585 </example>
3586 </member> 3284 </member>
3587 <member name="M:HttpServer.Rules.RegexRedirectRule.#ctor(System.String,System.String,System.Text.RegularExpressions.RegexOptions)"> 3285 <member name="M:HttpServer.IHttpResponse.Send">
3588 <summary> 3286 <summary>
3589 Initializes a new instance of the <see cref="T:HttpServer.Rules.RegexRedirectRule"/> class. 3287 Send headers and body to the browser.
3590 </summary> 3288 </summary>
3591 <param name="fromUrlExpression">Expression to match URL</param> 3289 <exception cref="T:System.InvalidOperationException">If content have already been sent.</exception>
3592 <param name="toUrlExpression">Expression to generate URL</param>
3593 <param name="options">Regular expression options to use, can be null</param>
3594 <example>
3595 <![CDATA[
3596 server.Add(new RegexRedirectRule("/(?<first>[a-zA-Z0-9]+)", "/user/{first}", RegexOptions.IgnoreCase));
3597 Result of ie. /employee1 will then be /user/employee1
3598 ]]>
3599 </example>
3600 </member> 3290 </member>
3601 <member name="M:HttpServer.Rules.RegexRedirectRule.#ctor(System.String,System.String,System.Text.RegularExpressions.RegexOptions,System.Boolean)"> 3291 <member name="M:HttpServer.IHttpResponse.SendBody(System.Byte[],System.Int32,System.Int32)">
3602 <summary> 3292 <summary>
3603 Initializes a new instance of the <see cref="T:HttpServer.Rules.RegexRedirectRule"/> class. 3293 Make sure that you have specified ContentLength and sent the headers first.
3294 </summary>
3295 <param name="buffer"></param>
3296 <exception cref="T:System.InvalidOperationException">If headers have not been sent.</exception>
3297 <see cref="M:HttpServer.IHttpResponse.SendHeaders"/>
3298 <param name="offset">offest of first byte to send</param>
3299 <param name="count">number of bytes to send.</param>
3300 <seealso cref="M:HttpServer.IHttpResponse.Send"/>
3301 <seealso cref="M:HttpServer.IHttpResponse.SendHeaders"/>
3302 <remarks>This method can be used if you want to send body contents without caching them first. This
3303 is recommended for larger files to keep the memory usage low.</remarks>
3304 </member>
3305 <member name="M:HttpServer.IHttpResponse.SendBody(System.Byte[])">
3306 <summary>
3307 Make sure that you have specified ContentLength and sent the headers first.
3308 </summary>
3309 <param name="buffer"></param>
3310 <exception cref="T:System.InvalidOperationException">If headers have not been sent.</exception>
3311 <see cref="M:HttpServer.IHttpResponse.SendHeaders"/>
3312 <seealso cref="M:HttpServer.IHttpResponse.Send"/>
3313 <seealso cref="M:HttpServer.IHttpResponse.SendHeaders"/>
3314 <remarks>This method can be used if you want to send body contents without caching them first. This
3315 is recommended for larger files to keep the memory usage low.</remarks>
3316 </member>
3317 <member name="M:HttpServer.IHttpResponse.SendHeaders">
3318 <summary>
3319 Send headers to the client.
3320 </summary>
3321 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
3322 <seealso cref="M:HttpServer.IHttpResponse.AddHeader(System.String,System.String)"/>
3323 <seealso cref="M:HttpServer.IHttpResponse.Send"/>
3324 <seealso cref="M:HttpServer.IHttpResponse.SendBody(System.Byte[])"/>
3325 </member>
3326 <member name="M:HttpServer.IHttpResponse.Redirect(System.Uri)">
3327 <summary>
3328 Redirect client to somewhere else using the 302 status code.
3329 </summary>
3330 <param name="uri">Destination of the redirect</param>
3331 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
3332 <remarks>You can not do anything more with the request when a redirect have been done. This should be your last
3333 action.</remarks>
3334 </member>
3335 <member name="M:HttpServer.IHttpResponse.Redirect(System.String)">
3336 <summary>
3337 redirect to somewhere
3338 </summary>
3339 <param name="url">where the redirect should go</param>
3340 <remarks>
3341 No body are allowed when doing redirects.
3342 </remarks>
3343 </member>
3344 <member name="P:HttpServer.IHttpResponse.Body">
3345 <summary>
3346 The body stream is used to cache the body contents
3347 before sending everything to the client. It's the simplest
3348 way to serve documents.
3349 </summary>
3350 </member>
3351 <member name="P:HttpServer.IHttpResponse.ProtocolVersion">
3352 <summary>
3353 Defines the version of the HTTP Response for applications where it's required
3354 for this to be forced.
3355 </summary>
3356 </member>
3357 <member name="P:HttpServer.IHttpResponse.Chunked">
3358 <summary>
3359 The chunked encoding modifies the body of a message in order to
3360 transfer it as a series of chunks, each with its own size indicator,
3361 followed by an OPTIONAL trailer containing entity-header fields. This
3362 allows dynamically produced content to be transferred along with the
3363 information necessary for the recipient to verify that it has
3364 received the full message.
3365 </summary>
3366 </member>
3367 <member name="P:HttpServer.IHttpResponse.Connection">
3368 <summary>
3369 Kind of connection
3370 </summary>
3371 </member>
3372 <member name="P:HttpServer.IHttpResponse.Encoding">
3373 <summary>
3374 Encoding to use when sending stuff to the client.
3375 </summary>
3376 <remarks>Default is UTF8</remarks>
3377 </member>
3378 <member name="P:HttpServer.IHttpResponse.KeepAlive">
3379 <summary>
3380 Number of seconds to keep connection alive
3381 </summary>
3382 <remarks>Only used if Connection property is set to ConnectionType.KeepAlive</remarks>
3383 </member>
3384 <member name="P:HttpServer.IHttpResponse.Status">
3385 <summary>
3386 Status code that is sent to the client.
3387 </summary>
3388 <remarks>Default is HttpStatusCode.Ok</remarks>
3389 </member>
3390 <member name="P:HttpServer.IHttpResponse.Reason">
3391 <summary>
3392 Information about why a specific status code was used.
3393 </summary>
3394 </member>
3395 <member name="P:HttpServer.IHttpResponse.ContentLength">
3396 <summary>
3397 Size of the body. MUST be specified before sending the header,
3398 unless property Chunked is set to true.
3399 </summary>
3400 </member>
3401 <member name="P:HttpServer.IHttpResponse.ContentType">
3402 <summary>
3403 Kind of content in the body
3404 </summary>
3405 <remarks>Default is text/html</remarks>
3406 </member>
3407 <member name="P:HttpServer.IHttpResponse.HeadersSent">
3408 <summary>
3409 Headers have been sent to the client-
3410 </summary>
3411 <remarks>You can not send any additional headers if they have already been sent.</remarks>
3412 </member>
3413 <member name="P:HttpServer.IHttpResponse.Sent">
3414 <summary>
3415 The whole response have been sent.
3416 </summary>
3417 </member>
3418 <member name="P:HttpServer.IHttpResponse.Cookies">
3419 <summary>
3420 Cookies that should be created/changed.
3421 </summary>
3422 </member>
3423 <member name="T:HttpServer.ConnectionType">
3424 <summary>
3425 Type of HTTP connection
3426 </summary>
3427 </member>
3428 <member name="F:HttpServer.ConnectionType.Close">
3429 <summary>
3430 Connection is closed after each request-response
3431 </summary>
3432 </member>
3433 <member name="F:HttpServer.ConnectionType.KeepAlive">
3434 <summary>
3435 Connection is kept alive for X seconds (unless another request have been made)
3436 </summary>
3437 </member>
3438 <member name="T:HttpServer.HttpModules.WebSiteModule">
3439 <summary>
3440 The website module let's you handle multiple websites in the same server.
3441 It uses the "Host" header to check which site you want.
3442 </summary>
3443 <remarks>It's recommended that you do not
3444 add any other modules to HttpServer if you are using the website module. Instead,
3445 add all wanted modules to each website.</remarks>
3446 </member>
3447 <member name="M:HttpServer.HttpModules.WebSiteModule.#ctor(System.String,System.String)">
3448 <summary>
3449
3450 </summary>
3451 <param name="host">domain name that should be handled.</param>
3452 <param name="name"></param>
3453 </member>
3454 <member name="M:HttpServer.HttpModules.WebSiteModule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)">
3455 <summary>
3456 Method that process the url
3457 </summary>
3458 <param name="request">Information sent by the browser about the request</param>
3459 <param name="response">Information that is being sent back to the client.</param>
3460 <param name="session">Session used to </param>
3461 </member>
3462 <member name="P:HttpServer.HttpModules.WebSiteModule.SiteName">
3463 <summary>
3464 Name of site.
3465 </summary>
3466 </member>
3467 <member name="T:HttpServer.HttpModules.HttpModuleExceptionEventArgs">
3468 <summary>
3469 Used to inform http server that
3470 </summary>
3471 </member>
3472 <member name="M:HttpServer.HttpModules.HttpModuleExceptionEventArgs.#ctor(System.Exception)">
3473 <summary>
3474 Eventarguments used when an exception is thrown by a module
3475 </summary>
3476 <param name="e">the exception</param>
3477 </member>
3478 <member name="P:HttpServer.HttpModules.HttpModuleExceptionEventArgs.Exception">
3479 <summary>
3480 Exception thrown in a module
3481 </summary>
3482 </member>
3483 <member name="T:HttpServer.HttpInputItem">
3484 <summary>
3485 represents a HTTP input item. Each item can have multiple sub items, a sub item
3486 is made in a HTML form by using square brackets
3604 </summary> 3487 </summary>
3605 <param name="fromUrlExpression">Expression to match URL</param>
3606 <param name="toUrlExpression">Expression to generate URL</param>
3607 <param name="options">Regular expression options to apply</param>
3608 <param name="shouldRedirect"><c>true</c> if request should be redirected, <c>false</c> if the request URI should be replaced.</param>
3609 <example> 3488 <example>
3610 <![CDATA[ 3489 // <input type="text" name="user[FirstName]" value="jonas" /> becomes:
3611 server.Add(new RegexRedirectRule("/(?<first>[a-zA-Z0-9]+)", "/user/${first}", RegexOptions.None)); 3490 Console.WriteLine("Value: {0}", form["user"]["FirstName"].Value);
3612 Result of ie. /employee1 will then be /user/employee1
3613 ]]>
3614 </example> 3491 </example>
3492 <remarks>
3493 All names in a form SHOULD be in lowercase.
3494 </remarks>
3495 </member>
3496 <member name="F:HttpServer.HttpInputItem.Empty">
3497 <summary> Representation of a non-initialized <see cref="T:HttpServer.HttpInputItem"/>.</summary>
3498 </member>
3499 <member name="M:HttpServer.HttpInputItem.#ctor(System.String,System.String)">
3500 <summary>
3501 Initializes an input item setting its name/identifier and value
3502 </summary>
3503 <param name="name">Parameter name/id</param>
3504 <param name="value">Parameter value</param>
3505 </member>
3506 <member name="M:HttpServer.HttpInputItem.#ctor(HttpServer.HttpInputItem)">
3507 <summary>Creates a deep copy of the item specified</summary>
3508 <param name="item">The item to copy</param>
3509 <remarks>The function makes a deep copy of quite a lot which can be slow</remarks>
3510 </member>
3511 <member name="M:HttpServer.HttpInputItem.Add(System.String)">
3512 <summary>
3513 Add another value to this item
3514 </summary>
3515 <param name="value">Value to add.</param>
3516 <exception cref="T:System.InvalidOperationException">Cannot add stuff to <see cref="F:HttpServer.HttpInput.Empty"/>.</exception>
3517 </member>
3518 <member name="M:HttpServer.HttpInputItem.Contains(System.String)">
3519 <summary>
3520 checks if a sub-item exists (and has a value).
3521 </summary>
3522 <param name="name">name in lower case</param>
3523 <returns>true if the sub-item exists and has a value; otherwise false.</returns>
3524 </member>
3525 <member name="M:HttpServer.HttpInputItem.ToString">
3526 <summary> Returns a formatted representation of the instance with the values of all contained parameters </summary>
3527 </member>
3528 <member name="M:HttpServer.HttpInputItem.ToString(System.String,System.Boolean)">
3529 <summary>
3530 Outputs the string in a formatted manner
3531 </summary>
3532 <param name="prefix">A prefix to append, used internally</param>
3533 <param name="asQuerySting">produce a query string</param>
3534 </member>
3535 <member name="M:HttpServer.HttpInputItem.Add(System.String,System.String)">
3536 <summary>
3537 Add a sub item.
3538 </summary>
3539 <param name="name">Can contain array formatting, the item is then parsed and added in multiple levels</param>
3540 <param name="value">Value to add.</param>
3615 <exception cref="T:System.ArgumentNullException">Argument is null.</exception> 3541 <exception cref="T:System.ArgumentNullException">Argument is null.</exception>
3616 <seealso cref="P:HttpServer.Rules.RedirectRule.ShouldRedirect"/> 3542 <exception cref="T:System.InvalidOperationException">Cannot add stuff to <see cref="F:HttpServer.HttpInput.Empty"/>.</exception>
3617 </member> 3543 </member>
3618 <member name="M:HttpServer.Rules.RegexRedirectRule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse)"> 3544 <member name="M:HttpServer.HttpInputItem.System#Collections#Generic#IEnumerable{HttpServer#HttpInputItem}#GetEnumerator">
3619 <summary> 3545 <summary>
3620 Process the incoming request. 3546 Returns an enumerator that iterates through the collection.
3621 </summary> 3547 </summary>
3622 <param name="request">incoming HTTP request</param> 3548
3623 <param name="response">outgoing HTTP response</param> 3549 <returns>
3624 <returns>true if response should be sent to the browser directly (no other rules or modules will be processed).</returns> 3550 A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> that can be used to iterate through the collection.
3625 <remarks> 3551 </returns>
3626 returning true means that no modules will get the request. Returning true is typically being done 3552 <filterpriority>1</filterpriority>
3627 for redirects. 3553 </member>
3628 </remarks> 3554 <member name="M:HttpServer.HttpInputItem.GetEnumerator">
3629 <exception cref="T:System.ArgumentNullException">If request or response is null</exception> 3555 <summary>
3556 Returns an enumerator that iterates through a collection.
3557 </summary>
3558
3559 <returns>
3560 An <see cref="T:System.Collections.IEnumerator"></see> object that can be used to iterate through the collection.
3561 </returns>
3562 <filterpriority>2</filterpriority>
3563 </member>
3564 <member name="M:HttpServer.HttpInputItem.ToString(System.String)">
3565 <summary>
3566 Outputs the string in a formatted manner
3567 </summary>
3568 <param name="prefix">A prefix to append, used internally</param>
3569 <returns></returns>
3570 </member>
3571 <member name="P:HttpServer.HttpInputItem.Count">
3572 <summary>
3573 Number of values
3574 </summary>
3575 </member>
3576 <member name="P:HttpServer.HttpInputItem.Item(System.String)">
3577 <summary>
3578 Get a sub item
3579 </summary>
3580 <param name="name">name in lower case.</param>
3581 <returns><see cref="F:HttpServer.HttpInputItem.Empty"/> if no item was found.</returns>
3582 </member>
3583 <member name="P:HttpServer.HttpInputItem.Name">
3584 <summary>
3585 Name of item (in lower case).
3586 </summary>
3587 </member>
3588 <member name="P:HttpServer.HttpInputItem.Value">
3589 <summary>
3590 Returns the first value, or null if no value exist.
3591 </summary>
3592 </member>
3593 <member name="P:HttpServer.HttpInputItem.LastValue">
3594 <summary>
3595 Returns the last value, or null if no value exist.
3596 </summary>
3597 </member>
3598 <member name="P:HttpServer.HttpInputItem.Values">
3599 <summary>
3600 Returns the list with values.
3601 </summary>
3602 </member>
3603 <member name="P:HttpServer.HttpInputItem.HttpServer#IHttpInput#Item(System.String)">
3604 <summary>
3605
3606 </summary>
3607 <param name="name">name in lower case</param>
3608 <returns></returns>
3609 </member>
3610 <member name="T:HttpServer.Helpers.ResourceManager">
3611 <summary>Class to handle loading of resource files</summary>
3612 </member>
3613 <member name="M:HttpServer.Helpers.ResourceManager.#ctor">
3614 <summary>
3615 Initializes a new instance of the <see cref="T:HttpServer.Helpers.ResourceManager"/> class.
3616 </summary>
3617 </member>
3618 <member name="M:HttpServer.Helpers.ResourceManager.#ctor(HttpServer.ILogWriter)">
3619 <summary>
3620 Initializes a new instance of the <see cref="T:HttpServer.Helpers.ResourceManager"/> class.
3621 </summary>
3622 <param name="writer">logger.</param>
3623 </member>
3624 <member name="M:HttpServer.Helpers.ResourceManager.LoadResources(System.String,System.Reflection.Assembly,System.String)">
3625 <summary>
3626 Loads resources from a namespace in the given assembly to an URI
3627 </summary>
3628 <param name="toUri">The URI to map the resources to</param>
3629 <param name="fromAssembly">The assembly in which the resources reside</param>
3630 <param name="fromNamespace">The namespace from which to load the resources</param>
3631 <usage>
3632 <code>
3633 resourceLoader.LoadResources("/user/", typeof(User).Assembly, "MyLib.Models.User.Views");
3634 </code>
3635 Will make the resource MyLib.Models.User.Views.list.Haml accessible via /user/list.haml or /user/list/
3636 </usage>
3637 <returns>The amount of loaded files, giving you the possibility of making sure the resources needed gets loaded</returns>
3638 <exception cref="T:System.InvalidOperationException">If a resource has already been mapped to an uri</exception>
3639 </member>
3640 <member name="M:HttpServer.Helpers.ResourceManager.GetResourceStream(System.String)">
3641 <summary>
3642 Retrieves a stream for the specified resource path if loaded otherwise null
3643 </summary>
3644 <param name="path">Path to the resource to retrieve a stream for</param>
3645 <returns>A stream or null if the resource couldn't be found</returns>
3646 </member>
3647 <member name="M:HttpServer.Helpers.ResourceManager.GetFiles(System.String)">
3648 <summary>
3649 Fetch all files from the resource that matches the specified arguments.
3650 </summary>
3651 <param name="path">The path to the resource to extract</param>
3652 <returns>
3653 a list of files if found; or an empty array if no files are found.
3654 </returns>
3655 <exception cref="T:System.ArgumentException">Search path must end with an asterisk for finding arbitrary files</exception>
3656 </member>
3657 <member name="M:HttpServer.Helpers.ResourceManager.GetFiles(System.String,System.String)">
3658 <summary>
3659 Fetch all files from the resource that matches the specified arguments.
3660 </summary>
3661 <param name="path">Where the file should reside.</param>
3662 <param name="filename">Files to check</param>
3663 <returns>
3664 a list of files if found; or an empty array if no files are found.
3665 </returns>
3666 </member>
3667 <member name="M:HttpServer.Helpers.ResourceManager.ContainsResource(System.String)">
3668 <summary>
3669 Returns whether or not the loader has an instance of the file requested
3670 </summary>
3671 <param name="filename">The name of the template/file</param>
3672 <returns>True if the loader can provide the file</returns>
3630 </member> 3673 </member>
3631 <member name="T:HttpServer.Parser.RequestLineEventArgs"> 3674 <member name="T:HttpServer.Parser.RequestLineEventArgs">
3632 <summary> 3675 <summary>
@@ -3664,908 +3707,849 @@
3664 Gets or sets requested URI path. 3707 Gets or sets requested URI path.
3665 </summary> 3708 </summary>
3666 </member> 3709 </member>
3667 <member name="T:HttpServer.RealmHandler"> 3710 <member name="T:HttpServer.IHttpContextHandler">
3668 <summary> 3711 <summary>
3669 Delegate used to find a realm/domain. 3712 Class that receives Requests from a <see cref="T:HttpServer.IHttpClientContext"/>.
3713 </summary>
3714 </member>
3715 <member name="M:HttpServer.IHttpContextHandler.ClientDisconnected(HttpServer.IHttpClientContext,System.Net.Sockets.SocketError)">
3716 <summary>
3717 Client have been disconnected.
3718 </summary>
3719 <param name="client">Client that was disconnected.</param>
3720 <param name="error">Reason</param>
3721 <see cref="T:HttpServer.IHttpClientContext"/>
3722 </member>
3723 <member name="M:HttpServer.IHttpContextHandler.RequestReceived(HttpServer.IHttpClientContext,HttpServer.IHttpRequest)">
3724 <summary>
3725 Invoked when a client context have received a new HTTP request
3726 </summary>
3727 <param name="client">Client that received the request.</param>
3728 <param name="request">Request that was received.</param>
3729 <see cref="T:HttpServer.IHttpClientContext"/>
3730 </member>
3731 <member name="T:HttpServer.HttpForm">
3732 <summary>Container for posted form data</summary>
3733 </member>
3734 <member name="F:HttpServer.HttpForm.EmptyForm">
3735 <summary>Instance to help mark a non-initialized form</summary>
3736 </member>
3737 <member name="M:HttpServer.HttpForm.#ctor">
3738 <summary>Initializes a form container with the specified name</summary>
3739 </member>
3740 <member name="M:HttpServer.HttpForm.#ctor(HttpServer.HttpInput)">
3741 <summary>
3742 Makes a deep copy of the input
3743 </summary>
3744 <param name="input">The input to copy</param>
3745 </member>
3746 <member name="M:HttpServer.HttpForm.AddFile(HttpServer.HttpFile)">
3747 <summary>
3748 Adds a file to the collection of posted files
3749 </summary>
3750 <param name="file">The file to add</param>
3751 <exception cref="T:System.ArgumentException">If the file is already added</exception>
3752 <exception cref="T:System.ArgumentNullException">If file is null</exception>
3753 <exception cref="T:System.InvalidOperationException">If the instance is HttpForm.EmptyForm which cannot be modified</exception>
3754 </member>
3755 <member name="M:HttpServer.HttpForm.ContainsFile(System.String)">
3756 <summary>
3757 Checks if the form contains a specified file
3758 </summary>
3759 <param name="name">Field name of the file parameter</param>
3760 <returns>True if the file exists</returns>
3761 <exception cref="T:System.InvalidOperationException">If the instance is HttpForm.EmptyForm which cannot be modified</exception>
3762 </member>
3763 <member name="M:HttpServer.HttpForm.GetFile(System.String)">
3764 <summary>
3765 Retrieves a file held by by the form
3766 </summary>
3767 <param name="name">The identifier of the file</param>
3768 <returns>The requested file or null if the file was not found</returns>
3769 <exception cref="T:System.ArgumentNullException">If name is null or empty</exception>
3770 <exception cref="T:System.InvalidOperationException">If the instance is HttpForm.EmptyForm which cannot be modified</exception>
3771 </member>
3772 <member name="M:HttpServer.HttpForm.Clear">
3773 <summary>Disposes all held HttpFile's and resets values</summary>
3774 </member>
3775 <member name="P:HttpServer.HttpForm.Files">
3776 <summary>
3777 Retrieves the number of files added to the <see cref="T:HttpServer.HttpForm"/>
3778 </summary>
3779 <returns>0 if no files are added</returns>
3780 </member>
3781 <member name="T:HttpServer.HttpClientContext">
3782 <summary>
3783 Contains a connection to a browser/client.
3670 </summary> 3784 </summary>
3671 <param name="domain"></param>
3672 <returns></returns>
3673 <remarks> 3785 <remarks>
3674 Realms are used during HTTP Authentication 3786 Remember to <see cref="M:HttpServer.HttpClientContext.Start"/> after you have hooked the <see cref="E:HttpServer.HttpClientContext.RequestReceived"/> event.
3675 </remarks> 3787 </remarks>
3676 <seealso cref="T:HttpServer.Authentication.AuthenticationModule"/> 3788 TODO: Maybe this class should be broken up into HttpClientChannel and HttpClientContext?
3677 <seealso cref="T:HttpServer.Authentication.AuthenticationHandler"/>
3678 </member> 3789 </member>
3679 <member name="T:HttpServer.HttpServer"> 3790 <member name="M:HttpServer.HttpClientContext.#ctor(System.Boolean,System.Net.IPEndPoint,System.IO.Stream,HttpServer.IRequestParserFactory,System.Int32,System.Net.Sockets.Socket)">
3680 <summary> 3791 <summary>
3681 A complete HTTP server, you need to add a module to it to be able to handle incoming requests. 3792 Initializes a new instance of the <see cref="T:HttpServer.HttpClientContext"/> class.
3682 </summary> 3793 </summary>
3683 <example> 3794 <param name="secured">true if the connection is secured (SSL/TLS)</param>
3684 <code> 3795 <param name="remoteEndPoint">client that connected.</param>
3685 // this small example will add two web site modules, thus handling 3796 <param name="stream">Stream used for communication</param>
3686 // two different sites. In reality you should add Controller modules or something 3797 <param name="parserFactory">Used to create a <see cref="T:HttpServer.IHttpRequestParser"/>.</param>
3687 // two the website modules to be able to handle different requests. 3798 <param name="bufferSize">Size of buffer to use when reading data. Must be at least 4096 bytes.</param>
3688 HttpServer server = new HttpServer(); 3799 <exception cref="T:System.Net.Sockets.SocketException">If <see cref="M:System.Net.Sockets.Socket.BeginReceive(System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.AsyncCallback,System.Object)"/> fails</exception>
3689 server.Add(new WebSiteModule("www.gauffin.com", "Gauffin Telecom AB")); 3800 <exception cref="T:System.ArgumentException">Stream must be writable and readable.</exception>
3690 server.Add(new WebSiteModule("www.vapadi.se", "Remote PBX")); 3801 </member>
3691 3802 <member name="M:HttpServer.HttpClientContext.OnBodyBytesReceived(System.Object,HttpServer.Parser.BodyEventArgs)">
3692 // start regular http 3803 <summary>
3693 server.Start(IPAddress.Any, 80); 3804 Process incoming body bytes.
3805 </summary>
3806 <param name="sender"><see cref="T:HttpServer.IHttpRequestParser"/></param>
3807 <param name="e">Bytes</param>
3808 </member>
3809 <member name="M:HttpServer.HttpClientContext.OnHeaderReceived(System.Object,HttpServer.Parser.HeaderEventArgs)">
3810 <summary>
3694 3811
3695 // start https 3812 </summary>
3696 server.Start(IPAddress.Any, 443, myCertificate); 3813 <param name="sender"></param>
3697 </code> 3814 <param name="e"></param>
3698 </example>
3699 <seealso cref="T:HttpServer.HttpModules.HttpModule"/>
3700 <seealso cref="T:HttpServer.HttpModules.FileModule"/>
3701 <seealso cref="T:HttpServer.HttpListener"/>
3702 </member> 3815 </member>
3703 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.IComponentProvider)"> 3816 <member name="M:HttpServer.HttpClientContext.Start">
3704 <summary> 3817 <summary>
3705 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class. 3818 Start reading content.
3706 </summary> 3819 </summary>
3707 <param name="provider">Used to get all components used in the server..</param> 3820 <remarks>
3821 Make sure to call base.Start() if you override this method.
3822 </remarks>
3708 </member> 3823 </member>
3709 <member name="M:HttpServer.HttpServer.#ctor"> 3824 <member name="M:HttpServer.HttpClientContext.Cleanup">
3710 <summary> 3825 <summary>
3711 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class. 3826 Clean up context.
3712 </summary> 3827 </summary>
3828 <remarks>
3829 Make sure to call base.Cleanup() if you override the method.
3830 </remarks>
3713 </member> 3831 </member>
3714 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.FormDecoders.FormDecoderProvider)"> 3832 <member name="M:HttpServer.HttpClientContext.Disconnect(System.Net.Sockets.SocketError)">
3715 <summary> 3833 <summary>
3716 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class. 3834 Disconnect from client
3717 </summary> 3835 </summary>
3718 <param name="decoderProvider">Form decoders are used to convert different types of posted data to the <see cref="T:HttpServer.HttpInput"/> object types.</param> 3836 <param name="error">error to report in the <see cref="E:HttpServer.HttpClientContext.Disconnected"/> event.</param>
3719 <seealso cref="T:HttpServer.FormDecoders.IFormDecoder"/>
3720 <seealso cref="P:HttpServer.HttpServer.FormDecoderProviders"/>
3721 </member> 3837 </member>
3722 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.Sessions.IHttpSessionStore)"> 3838 <member name="M:HttpServer.HttpClientContext.Respond(System.String,System.Net.HttpStatusCode,System.String,System.String,System.String)">
3723 <summary> 3839 <summary>
3724 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class. 3840 Send a response.
3725 </summary> 3841 </summary>
3726 <param name="sessionStore">A session store is used to save and retrieve sessions</param> 3842 <param name="httpVersion">Either <see cref="F:HttpServer.HttpHelper.HTTP10"/> or <see cref="F:HttpServer.HttpHelper.HTTP11"/></param>
3727 <seealso cref="T:HttpServer.Sessions.IHttpSessionStore"/> 3843 <param name="statusCode">HTTP status code</param>
3844 <param name="reason">reason for the status code.</param>
3845 <param name="body">HTML body contents, can be null or empty.</param>
3846 <param name="contentType">A content type to return the body as, i.e. 'text/html' or 'text/plain', defaults to 'text/html' if null or empty</param>
3847 <exception cref="T:System.ArgumentException">If <paramref name="httpVersion"/> is invalid.</exception>
3728 </member> 3848 </member>
3729 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.ILogWriter)"> 3849 <member name="M:HttpServer.HttpClientContext.Respond(System.String,System.Net.HttpStatusCode,System.String)">
3730 <summary> 3850 <summary>
3731 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class. 3851 Send a response.
3732 </summary> 3852 </summary>
3733 <param name="logWriter">The log writer.</param> 3853 <param name="httpVersion">Either <see cref="F:HttpServer.HttpHelper.HTTP10"/> or <see cref="F:HttpServer.HttpHelper.HTTP11"/></param>
3734 <seealso cref="P:HttpServer.HttpServer.LogWriter"/> 3854 <param name="statusCode">HTTP status code</param>
3855 <param name="reason">reason for the status code.</param>
3735 </member> 3856 </member>
3736 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.FormDecoders.FormDecoderProvider,HttpServer.ILogWriter)"> 3857 <member name="M:HttpServer.HttpClientContext.Respond(System.String)">
3737 <summary> 3858 <summary>
3738 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class. 3859 Send a response.
3739 </summary> 3860 </summary>
3740 <param name="decoderProvider">Form decoders are used to convert different types of posted data to the <see cref="T:HttpServer.HttpInput"/> object types.</param> 3861 <exception cref="T:System.ArgumentNullException"></exception>
3741 <param name="logWriter">The log writer.</param>
3742 <seealso cref="T:HttpServer.FormDecoders.IFormDecoder"/>
3743 <seealso cref="P:HttpServer.HttpServer.FormDecoderProviders"/>
3744 <seealso cref="P:HttpServer.HttpServer.LogWriter"/>
3745 </member> 3862 </member>
3746 <member name="M:HttpServer.HttpServer.#ctor(HttpServer.FormDecoders.FormDecoderProvider,HttpServer.Sessions.IHttpSessionStore,HttpServer.ILogWriter)"> 3863 <member name="M:HttpServer.HttpClientContext.Send(System.Byte[])">
3747 <summary> 3864 <summary>
3748 Initializes a new instance of the <see cref="T:HttpServer.HttpServer"/> class. 3865 send a whole buffer
3749 </summary> 3866 </summary>
3750 <param name="decoderProvider">Form decoders are used to convert different types of posted data to the <see cref="T:HttpServer.HttpInput"/> object types.</param> 3867 <param name="buffer">buffer to send</param>
3751 <param name="sessionStore">A session store is used to save and retrieve sessions</param> 3868 <exception cref="T:System.ArgumentNullException"></exception>
3752 <param name="logWriter">The log writer.</param>
3753 <seealso cref="T:HttpServer.FormDecoders.IFormDecoder"/>
3754 <seealso cref="P:HttpServer.HttpServer.FormDecoderProviders"/>
3755 <seealso cref="P:HttpServer.HttpServer.LogWriter"/>
3756 <seealso cref="T:HttpServer.Sessions.IHttpSessionStore"/>
3757 </member> 3869 </member>
3758 <member name="M:HttpServer.HttpServer.Add(HttpServer.Rules.IRule)"> 3870 <member name="M:HttpServer.HttpClientContext.Send(System.Byte[],System.Int32,System.Int32)">
3759 <summary> 3871 <summary>
3760 Adds the specified rule. 3872 Send data using the stream
3761 </summary> 3873 </summary>
3762 <param name="rule">The rule.</param> 3874 <param name="buffer">Contains data to send</param>
3875 <param name="offset">Start position in buffer</param>
3876 <param name="size">number of bytes to send</param>
3877 <exception cref="T:System.ArgumentNullException"></exception>
3878 <exception cref="T:System.ArgumentOutOfRangeException"></exception>
3763 </member> 3879 </member>
3764 <member name="M:HttpServer.HttpServer.Add(HttpServer.HttpModules.HttpModule)"> 3880 <member name="E:HttpServer.HttpClientContext.Cleaned">
3765 <summary> 3881 <summary>
3766 Add a <see cref="T:HttpServer.HttpModules.HttpModule"/> to the server. 3882 This context have been cleaned, which means that it can be reused.
3767 </summary> 3883 </summary>
3768 <param name="module">mode to add</param>
3769 </member> 3884 </member>
3770 <member name="M:HttpServer.HttpServer.DecodeBody(HttpServer.IHttpRequest)"> 3885 <member name="E:HttpServer.HttpClientContext.Started">
3771 <summary> 3886 <summary>
3772 Decodes the request body. 3887 Context have been started (a new client have connected)
3773 </summary> 3888 </summary>
3774 <param name="request">The request.</param>
3775 <exception cref="T:HttpServer.Exceptions.InternalServerException">Failed to decode form data.</exception>
3776 </member> 3889 </member>
3777 <member name="M:HttpServer.HttpServer.ErrorPage(HttpServer.IHttpResponse,System.Net.HttpStatusCode,System.String)"> 3890 <member name="P:HttpServer.HttpClientContext.CurrentRequest">
3778 <summary> 3891 <summary>
3779 Generate a HTTP error page (that will be added to the response body). 3892 Overload to specify own type.
3780 response status code is also set.
3781 </summary> 3893 </summary>
3782 <param name="response">Response that the page will be generated in.</param> 3894 <remarks>
3783 <param name="error"><see cref="T:System.Net.HttpStatusCode"/>.</param> 3895 Must be specified before the context is being used.
3784 <param name="body">response body contents.</param> 3896 </remarks>
3785 </member> 3897 </member>
3786 <member name="M:HttpServer.HttpServer.ErrorPage(HttpServer.IHttpResponse,HttpServer.Exceptions.HttpException)"> 3898 <member name="P:HttpServer.HttpClientContext.Secured">
3787 <summary> 3899 <summary>
3788 Generate a HTTP error page (that will be added to the response body). 3900 Using SSL or other encryption method.
3789 response status code is also set.
3790 </summary> 3901 </summary>
3791 <param name="response">Response that the page will be generated in.</param>
3792 <param name="err">exception.</param>
3793 </member> 3902 </member>
3794 <member name="M:HttpServer.HttpServer.GetRealm(HttpServer.IHttpRequest)"> 3903 <member name="P:HttpServer.HttpClientContext.IsSecured">
3795 <summary> 3904 <summary>
3796 Realms are used by the <see cref="T:HttpServer.Authentication.AuthenticationModule"/>s. 3905 Using SSL or other encryption method.
3797 </summary> 3906 </summary>
3798 <param name="request">HTTP request</param>
3799 <returns>domain/realm.</returns>
3800 </member> 3907 </member>
3801 <member name="M:HttpServer.HttpServer.HandleRequest(HttpServer.IHttpClientContext,HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)"> 3908 <member name="P:HttpServer.HttpClientContext.LogWriter">
3802 <summary> 3909 <summary>
3803 Process an incoming request. 3910 Specify which logger to use.
3804 </summary> 3911 </summary>
3805 <param name="context">connection to client</param>
3806 <param name="request">request information</param>
3807 <param name="response">response that should be filled</param>
3808 <param name="session">session information</param>
3809 </member> 3912 </member>
3810 <member name="M:HttpServer.HttpServer.OnClientDisconnected(HttpServer.IHttpClientContext,System.Net.Sockets.SocketError)"> 3913 <member name="P:HttpServer.HttpClientContext.Stream">
3811 <summary> 3914 <summary>
3812 Can be overloaded to implement stuff when a client have been connected. 3915 Gets or sets the network stream.
3813 </summary> 3916 </summary>
3814 <remarks>
3815 Default implementation does nothing.
3816 </remarks>
3817 <param name="client">client that disconnected</param>
3818 <param name="error">disconnect reason</param>
3819 </member> 3917 </member>
3820 <member name="M:HttpServer.HttpServer.ProcessAuthentication(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)"> 3918 <member name="P:HttpServer.HttpClientContext.RemoteAddress">
3821 <summary> 3919 <summary>
3822 Handle authentication 3920 Gets or sets IP address that the client connected from.
3823 </summary> 3921 </summary>
3824 <param name="request"></param>
3825 <param name="response"></param>
3826 <param name="session"></param>
3827 <returns>true if request can be handled; false if not.</returns>
3828 <exception cref="T:HttpServer.Exceptions.BadRequestException">Invalid authorization header</exception>
3829 </member> 3922 </member>
3830 <member name="M:HttpServer.HttpServer.RequestAuthentication(HttpServer.Authentication.AuthenticationModule,HttpServer.IHttpRequest,HttpServer.IHttpResponse)"> 3923 <member name="P:HttpServer.HttpClientContext.RemotePort">
3831 <summary> 3924 <summary>
3832 Will request authentication. 3925 Gets or sets port that the client connected from.
3926 </summary>
3927 </member>
3928 <member name="E:HttpServer.HttpClientContext.Disconnected">
3929 <summary>
3930 The context have been disconnected.
3833 </summary> 3931 </summary>
3834 <remarks> 3932 <remarks>
3835 Sends respond to client, nothing else can be done with the response after this. 3933 Event can be used to clean up a context, or to reuse it.
3836 </remarks> 3934 </remarks>
3837 <param name="mod"></param>
3838 <param name="request"></param>
3839 <param name="response"></param>
3840 </member> 3935 </member>
3841 <member name="M:HttpServer.HttpServer.OnRequest(System.Object,HttpServer.RequestEventArgs)"> 3936 <member name="E:HttpServer.HttpClientContext.RequestReceived">
3842 <summary> 3937 <summary>
3843 Received from a <see cref="T:HttpServer.IHttpClientContext"/> when a request have been parsed successfully. 3938 A request have been received in the context.
3844 </summary> 3939 </summary>
3845 <param name="source"><see cref="T:HttpServer.IHttpClientContext"/> that received the request.</param>
3846 <param name="args">The request.</param>
3847 </member> 3940 </member>
3848 <member name="M:HttpServer.HttpServer.ProcessRequestWrapper(HttpServer.IHttpClientContext,HttpServer.IHttpRequest)"> 3941 <member name="T:HttpServer.Helpers.XmlHelper">
3849 <summary> 3942 <summary>
3850 To be able to track request count. 3943 Helpers to make XML handling easier
3851 </summary> 3944 </summary>
3852 <param name="context"></param>
3853 <param name="request"></param>
3854 </member> 3945 </member>
3855 <member name="M:HttpServer.HttpServer.Start(System.Net.IPAddress,System.Int32)"> 3946 <member name="M:HttpServer.Helpers.XmlHelper.Serialize(System.Object)">
3856 <summary> 3947 <summary>
3857 Start the web server using regular HTTP. 3948 Serializes object to XML.
3858 </summary> 3949 </summary>
3859 <param name="address">IP Address to listen on, use <c>IpAddress.Any </c>to accept connections on all IP addresses/network cards.</param> 3950 <param name="value">object to serialize.</param>
3860 <param name="port">Port to listen on. 80 can be a good idea =)</param> 3951 <returns>XML</returns>
3861 <exception cref="T:System.ArgumentNullException"><c>address</c> is null.</exception> 3952 <remarks>
3862 <exception cref="T:System.ArgumentException">Port must be a positive number.</exception> 3953 Removes name spaces and adds indentation
3954 </remarks>
3863 </member> 3955 </member>
3864 <member name="M:HttpServer.HttpServer.Start(System.Net.IPAddress,System.Int32,System.Security.Cryptography.X509Certificates.X509Certificate)"> 3956 <member name="M:HttpServer.Helpers.XmlHelper.Deserialize``1(System.String)">
3865 <summary> 3957 <summary>
3866 Accept secure connections. 3958 Create an object from a XML string
3867 </summary> 3959 </summary>
3868 <param name="address">IP Address to listen on, use <see cref="F:System.Net.IPAddress.Any"/> to accept connections on all IP Addresses / network cards.</param> 3960 <typeparam name="T">Type of object</typeparam>
3869 <param name="port">Port to listen on. 80 can be a good idea =)</param> 3961 <param name="xml">XML string</param>
3870 <param name="certificate">Certificate to use</param> 3962 <returns>object</returns>
3871 <exception cref="T:System.ArgumentNullException"><c>address</c> is null.</exception>
3872 <exception cref="T:System.ArgumentException">Port must be a positive number.</exception>
3873 </member> 3963 </member>
3874 <member name="M:HttpServer.HttpServer.Stop"> 3964 <member name="M:HttpServer.FormDecoders.HttpMultipart.ReadLine">
3875 <summary> 3965 <summary>
3876 shut down the server and listeners 3966
3877 </summary> 3967 </summary>
3968 <returns></returns>
3969 <exception cref="T:System.ArgumentOutOfRangeException"></exception>
3970 <exception cref="T:System.ObjectDisposedException"></exception>
3878 </member> 3971 </member>
3879 <member name="M:HttpServer.HttpServer.WriteLog(HttpServer.LogPrio,System.String)"> 3972 <member name="T:HttpServer.FormDecoders.HttpMultipart.Element">
3973 <summary>Represents a field in a multipart form</summary>
3974 </member>
3975 <member name="T:HttpServer.Check">
3880 <summary> 3976 <summary>
3881 write an entry to the log file 3977 Small design by contract implementation.
3882 </summary> 3978 </summary>
3883 <param name="prio">importance of the message</param>
3884 <param name="message">log message</param>
3885 </member> 3979 </member>
3886 <member name="M:HttpServer.HttpServer.WriteLog(System.Object,HttpServer.LogPrio,System.String)"> 3980 <member name="M:HttpServer.Check.NotEmpty(System.String,System.String)">
3887 <summary> 3981 <summary>
3888 write an entry to the log file 3982 Check whether a parameter is empty.
3889 </summary> 3983 </summary>
3890 <param name="source">object that wrote the message</param> 3984 <param name="value">Parameter value</param>
3891 <param name="prio">importance of the message</param> 3985 <param name="parameterOrErrorMessage">Parameter name, or error description.</param>
3892 <param name="message">log message</param> 3986 <exception cref="T:System.ArgumentException">value is empty.</exception>
3893 </member> 3987 </member>
3894 <member name="P:HttpServer.HttpServer.Current"> 3988 <member name="M:HttpServer.Check.Require(System.Object,System.String)">
3895 <summary> 3989 <summary>
3896 Server that is handling the current request. 3990 Checks whether a parameter is null.
3897 </summary> 3991 </summary>
3898 <remarks> 3992 <param name="value">Parameter value</param>
3899 Will be set as soon as a request arrives to the <see cref="T:HttpServer.HttpServer"/> object. 3993 <param name="parameterOrErrorMessage">Parameter name, or error description.</param>
3900 </remarks> 3994 <exception cref="T:System.ArgumentNullException">value is null.</exception>
3901 </member> 3995 </member>
3902 <member name="P:HttpServer.HttpServer.AuthenticationModules"> 3996 <member name="M:HttpServer.Check.Min(System.Int32,System.Object,System.String)">
3903 <summary> 3997 <summary>
3904 Modules used for authentication. The module that is is added first is used as 3998 Checks whether a parameter is null.
3905 the default authentication module.
3906 </summary> 3999 </summary>
3907 <remarks>Use the corresponding property 4000 <param name="minValue"></param>
3908 in the <see cref="T:HttpServer.HttpModules.WebSiteModule"/> if you are using multiple websites.</remarks> 4001 <param name="value">Parameter value</param>
4002 <param name="parameterOrErrorMessage">Parameter name, or error description.</param>
4003 <exception cref="T:System.ArgumentException">value is null.</exception>
3909 </member> 4004 </member>
3910 <member name="P:HttpServer.HttpServer.FormDecoderProviders"> 4005 <member name="T:HttpServer.LogPrio">
3911 <summary> 4006 <summary>
3912 Form decoder providers are used to decode request body (which normally contains form data). 4007 Priority for log entries
3913 </summary> 4008 </summary>
4009 <seealso cref="T:HttpServer.ILogWriter"/>
3914 </member> 4010 </member>
3915 <member name="P:HttpServer.HttpServer.ServerName"> 4011 <member name="F:HttpServer.LogPrio.Trace">
3916 <summary> 4012 <summary>
3917 Server name sent in HTTP responses. 4013 Very detailed logs to be able to follow the flow of the program.
3918 </summary> 4014 </summary>
3919 <remarks>
3920 Do NOT include version in name, since it makes it
3921 easier for hackers.
3922 </remarks>
3923 </member> 4015 </member>
3924 <member name="P:HttpServer.HttpServer.SessionCookieName"> 4016 <member name="F:HttpServer.LogPrio.Debug">
3925 <summary> 4017 <summary>
3926 Name of cookie where session id is stored. 4018 Logs to help debug errors in the application
3927 </summary> 4019 </summary>
3928 </member> 4020 </member>
3929 <member name="P:HttpServer.HttpServer.LogWriter"> 4021 <member name="F:HttpServer.LogPrio.Info">
3930 <summary> 4022 <summary>
3931 Specified where logging should go. 4023 Information to be able to keep track of state changes etc.
3932 </summary> 4024 </summary>
3933 <seealso cref="T:HttpServer.NullLogWriter"/>
3934 <seealso cref="T:HttpServer.ConsoleLogWriter"/>
3935 <seealso cref="P:HttpServer.HttpServer.LogWriter"/>
3936 </member> 4025 </member>
3937 <member name="P:HttpServer.HttpServer.BackLog"> 4026 <member name="F:HttpServer.LogPrio.Warning">
3938 <summary> 4027 <summary>
3939 Number of connections that can wait to be accepted by the server. 4028 Something did not go as we expected, but it's no problem.
3940 </summary> 4029 </summary>
3941 <remarks>Default is 10.</remarks>
3942 </member> 4030 </member>
3943 <member name="P:HttpServer.HttpServer.MaxRequestCount"> 4031 <member name="F:HttpServer.LogPrio.Error">
3944 <summary> 4032 <summary>
3945 Gets or sets maximum number of allowed simultaneous requests. 4033 Something that should not fail failed, but we can still keep
4034 on going.
3946 </summary> 4035 </summary>
3947 <remarks>
3948 <para>
3949 This property is useful in busy systems. The HTTP server
3950 will start queuing new requests if this limit is hit, instead
3951 of trying to process all incoming requests directly.
3952 </para>
3953 <para>
3954 The default number if allowed simultaneous requests are 10.
3955 </para>
3956 </remarks>
3957 </member> 4036 </member>
3958 <member name="P:HttpServer.HttpServer.MaxQueueSize"> 4037 <member name="F:HttpServer.LogPrio.Fatal">
3959 <summary> 4038 <summary>
3960 Gets or sets maximum number of requests queuing to be handled. 4039 Something failed, and we cannot handle it properly.
3961 </summary> 4040 </summary>
3962 <remarks>
3963 <para>
3964 The WebServer will start turning requests away if response code
3965 <see cref="F:System.Net.HttpStatusCode.ServiceUnavailable"/> to indicate that the server
3966 is too busy to be able to handle the request.
3967 </para>
3968 </remarks>
3969 </member> 4041 </member>
3970 <member name="E:HttpServer.HttpServer.RealmWanted"> 4042 <member name="T:HttpServer.ILogWriter">
3971 <summary> 4043 <summary>
3972 Realms are used during HTTP authentication. 4044 Interface used to write to log files.
3973 Default realm is same as server name.
3974 </summary> 4045 </summary>
3975 </member> 4046 </member>
3976 <member name="E:HttpServer.HttpServer.ExceptionThrown"> 4047 <member name="M:HttpServer.ILogWriter.Write(System.Object,HttpServer.LogPrio,System.String)">
3977 <summary> 4048 <summary>
3978 Let's to receive unhandled exceptions from the threads. 4049 Write an entry to the log file.
3979 </summary> 4050 </summary>
3980 <remarks> 4051 <param name="source">object that is writing to the log</param>
3981 Exceptions will be thrown during debug mode if this event is not used, 4052 <param name="priority">importance of the log message</param>
3982 exceptions will be printed to console and suppressed during release mode. 4053 <param name="message">the message</param>
3983 </remarks>
3984 </member> 4054 </member>
3985 <member name="T:HttpServer.Exceptions.UnauthorizedException"> 4055 <member name="T:HttpServer.ConsoleLogWriter">
3986 <summary> 4056 <summary>
3987 The request requires user authentication. The response MUST include a 4057 This class writes to the console. It colors the output depending on the logprio and includes a 3-level stacktrace (in debug mode)
3988 WWW-Authenticate header field (section 14.47) containing a challenge
3989 applicable to the requested resource.
3990
3991 The client MAY repeat the request with a suitable Authorization header
3992 field (section 14.8). If the request already included Authorization
3993 credentials, then the 401 response indicates that authorization has been
3994 refused for those credentials. If the 401 response contains the same challenge
3995 as the prior response, and the user agent has already attempted authentication
3996 at least once, then the user SHOULD be presented the entity that was given in the response,
3997 since that entity might include relevant diagnostic information.
3998
3999 HTTP access authentication is explained in rfc2617:
4000 http://www.ietf.org/rfc/rfc2617.txt
4001
4002 (description is taken from
4003 http://www.submissionchamber.com/help-guides/error-codes.php#sec10.4.2)
4004 </summary> 4058 </summary>
4059 <seealso cref="T:HttpServer.ILogWriter"/>
4005 </member> 4060 </member>
4006 <member name="M:HttpServer.Exceptions.UnauthorizedException.#ctor"> 4061 <member name="F:HttpServer.ConsoleLogWriter.Instance">
4007 <summary> 4062 <summary>
4008 Create a new unauhtorized exception. 4063 The actual instance of this class.
4009 </summary> 4064 </summary>
4010 <seealso cref="T:HttpServer.Exceptions.UnauthorizedException"/>
4011 </member> 4065 </member>
4012 <member name="M:HttpServer.Exceptions.UnauthorizedException.#ctor(System.String,System.Exception)"> 4066 <member name="M:HttpServer.ConsoleLogWriter.Write(System.Object,HttpServer.LogPrio,System.String)">
4013 <summary> 4067 <summary>
4014 Create a new unauhtorized exception. 4068 Logwriters the specified source.
4015 </summary> 4069 </summary>
4016 <param name="message">reason to why the request was unauthorized.</param> 4070 <param name="source">object that wrote the logentry.</param>
4017 <param name="inner">inner exception</param> 4071 <param name="prio">Importance of the log message</param>
4072 <param name="message">The message.</param>
4018 </member> 4073 </member>
4019 <member name="M:HttpServer.Exceptions.UnauthorizedException.#ctor(System.String)"> 4074 <member name="M:HttpServer.ConsoleLogWriter.GetColor(HttpServer.LogPrio)">
4020 <summary> 4075 <summary>
4021 Create a new unauhtorized exception. 4076 Get color for the specified logprio
4022 </summary> 4077 </summary>
4023 <param name="message">reason to why the request was unauthorized.</param> 4078 <param name="prio">prio for the log entry</param>
4079 <returns>A <see cref="T:System.ConsoleColor"/> for the prio</returns>
4024 </member> 4080 </member>
4025 <member name="T:HttpServer.ContentType"> 4081 <member name="T:HttpServer.NullLogWriter">
4026 <summary> 4082 <summary>
4027 Lists content type mime types. 4083 Default log writer, writes everything to null (nowhere).
4028 </summary> 4084 </summary>
4085 <seealso cref="T:HttpServer.ILogWriter"/>
4029 </member> 4086 </member>
4030 <member name="F:HttpServer.ContentType.Text"> 4087 <member name="F:HttpServer.NullLogWriter.Instance">
4031 <summary> 4088 <summary>
4032 text/plain 4089 The logging instance.
4033 </summary> 4090 </summary>
4034 </member> 4091 </member>
4035 <member name="F:HttpServer.ContentType.Html"> 4092 <member name="M:HttpServer.NullLogWriter.Write(System.Object,HttpServer.LogPrio,System.String)">
4036 <summary> 4093 <summary>
4037 text/haml 4094 Writes everything to null
4038 </summary> 4095 </summary>
4096 <param name="source">object that wrote the log entry.</param>
4097 <param name="prio">Importance of the log message</param>
4098 <param name="message">The message.</param>
4039 </member> 4099 </member>
4040 <member name="F:HttpServer.ContentType.Javascript"> 4100 <member name="T:HttpServer.HttpResponse">
4041 <summary> 4101 <summary>
4042 content type for javascript documents = application/javascript 4102 Response that is sent back to the web browser / client.
4043 </summary> 4103 </summary>
4044 <remarks> 4104 <remarks>
4045 <para> 4105 <para>
4046 RFC 4329 states that text/javascript have been superseeded by 4106 A response can be sent if different ways. The easiest one is
4047 application/javascript. You might still want to check browser versions 4107 to just fill the Body stream with content, everything else
4048 since older ones do not support application/javascript. 4108 will then be taken care of by the framework. The default content-type
4109 is text/html, you should change it if you send anything else.
4110 </para><para>
4111 The second and slightly more complex way is to send the response
4112 as parts. Start with sending the header using the SendHeaders method and
4113 then you can send the body using SendBody method, but do not forget
4114 to set <see cref="P:HttpServer.HttpResponse.ContentType"/> and <see cref="P:HttpServer.HttpResponse.ContentLength"/> before doing so.
4049 </para> 4115 </para>
4050 <para>Browser support: http://krijnhoetmer.nl/stuff/javascript/mime-types/</para>
4051 </remarks> 4116 </remarks>
4117 <example>
4118 <code>
4119 // Example using response body.
4120 class MyModule : HttpModule
4121 {
4122 public override bool Process(IHttpRequest request, IHttpResponse response, IHttpSession session)
4123 {
4124 StreamWriter writer = new StreamWriter(response.Body);
4125 writer.WriteLine("Hello dear World!");
4126 writer.Flush();
4127
4128 // return true to tell webserver that we've handled the url
4129 return true;
4130 }
4131 }
4132 </code>
4133 </example>
4134 todo: add two examples, using SendHeaders/SendBody and just the Body stream.
4052 </member> 4135 </member>
4053 <member name="F:HttpServer.ContentType.Xml"> 4136 <member name="M:HttpServer.HttpResponse.#ctor(HttpServer.IHttpClientContext,HttpServer.IHttpRequest)">
4054 <summary> 4137 <summary>
4055 text/xml 4138 Initializes a new instance of the <see cref="T:HttpServer.IHttpResponse"/> class.
4056 </summary> 4139 </summary>
4140 <param name="context">Client that send the <see cref="T:HttpServer.IHttpRequest"/>.</param>
4141 <param name="request">Contains information of what the client want to receive.</param>
4142 <exception cref="T:System.ArgumentException"><see cref="P:HttpServer.IHttpRequest.HttpVersion"/> cannot be empty.</exception>
4057 </member> 4143 </member>
4058 <member name="T:HttpServer.ContentTypes"> 4144 <member name="M:HttpServer.HttpResponse.#ctor(HttpServer.IHttpClientContext,System.String,HttpServer.ConnectionType)">
4059 <summary> 4145 <summary>
4060 A list of content types 4146 Initializes a new instance of the <see cref="T:HttpServer.IHttpResponse"/> class.
4061 </summary> 4147 </summary>
4148 <param name="context">Client that send the <see cref="T:HttpServer.IHttpRequest"/>.</param>
4149 <param name="httpVersion">Version of HTTP protocol that the client uses.</param>
4150 <param name="connectionType">Type of HTTP connection used.</param>
4062 </member> 4151 </member>
4063 <member name="M:HttpServer.ContentTypes.#ctor(System.String)"> 4152 <member name="M:HttpServer.HttpResponse.AddHeader(System.String,System.String)">
4064 <summary> 4153 <summary>
4065 4154 Add another header to the document.
4066 </summary> 4155 </summary>
4067 <param name="types">Semicolon separated content types.</param> 4156 <param name="name">Name of the header, case sensitive, use lower cases.</param>
4157 <param name="value">Header values can span over multiple lines as long as each line starts with a white space. New line chars should be \r\n</param>
4158 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
4159 <exception cref="T:System.ArgumentException">If value conditions have not been met.</exception>
4160 <remarks>Adding any header will override the default ones and those specified by properties.</remarks>
4068 </member> 4161 </member>
4069 <member name="M:HttpServer.ContentTypes.GetEnumerator"> 4162 <member name="M:HttpServer.HttpResponse.Send">
4070 <summary> 4163 <summary>
4071 Returns an enumerator that iterates through a collection. 4164 Send headers and body to the browser.
4072 </summary> 4165 </summary>
4073 <returns> 4166 <exception cref="T:System.InvalidOperationException">If content have already been sent.</exception>
4074 An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
4075 </returns>
4076 </member> 4167 </member>
4077 <member name="M:HttpServer.ContentTypes.Contains(System.String)"> 4168 <member name="M:HttpServer.HttpResponse.SendBody(System.Byte[],System.Int32,System.Int32)">
4078 <summary> 4169 <summary>
4079 Searches for the specified type 4170 Make sure that you have specified <see cref="P:HttpServer.HttpResponse.ContentLength"/> and sent the headers first.
4080 </summary> 4171 </summary>
4081 <param name="type">Can also be a part of a type (searching for "xml" would return true for "application/xml").</param> 4172 <param name="buffer"></param>
4082 <returns>true if type was found.</returns> 4173 <exception cref="T:System.InvalidOperationException">If headers have not been sent.</exception>
4174 <see cref="M:HttpServer.HttpResponse.SendHeaders"/>
4175 <param name="offset">offset of first byte to send</param>
4176 <param name="count">number of bytes to send.</param>
4177 <seealso cref="M:HttpServer.HttpResponse.Send"/>
4178 <seealso cref="M:HttpServer.HttpResponse.SendHeaders"/>
4179 <remarks>This method can be used if you want to send body contents without caching them first. This
4180 is recommended for larger files to keep the memory usage low.</remarks>
4083 </member> 4181 </member>
4084 <member name="P:HttpServer.ContentTypes.First"> 4182 <member name="M:HttpServer.HttpResponse.SendBody(System.Byte[])">
4085 <summary> 4183 <summary>
4086 Get this first content type. 4184 Make sure that you have specified <see cref="P:HttpServer.HttpResponse.ContentLength"/> and sent the headers first.
4087 </summary> 4185 </summary>
4186 <param name="buffer"></param>
4187 <exception cref="T:System.InvalidOperationException">If headers have not been sent.</exception>
4188 <see cref="M:HttpServer.HttpResponse.SendHeaders"/>
4189 <seealso cref="M:HttpServer.HttpResponse.Send"/>
4190 <seealso cref="M:HttpServer.HttpResponse.SendHeaders"/>
4191 <remarks>This method can be used if you want to send body contents without caching them first. This
4192 is recommended for larger files to keep the memory usage low.</remarks>
4088 </member> 4193 </member>
4089 <member name="P:HttpServer.ContentTypes.Item(System.String)"> 4194 <member name="M:HttpServer.HttpResponse.SendHeaders">
4090 <summary> 4195 <summary>
4091 Fetch a content type 4196 Send headers to the client.
4092 </summary> 4197 </summary>
4093 <param name="type">Part of type ("xml" would return "application/xml")</param> 4198 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
4094 <returns></returns> 4199 <seealso cref="M:HttpServer.HttpResponse.AddHeader(System.String,System.String)"/>
4095 <remarks>All content types are in lower case.</remarks> 4200 <seealso cref="M:HttpServer.HttpResponse.Send"/>
4201 <seealso cref="M:HttpServer.HttpResponse.SendBody(System.Byte[])"/>
4096 </member> 4202 </member>
4097 <member name="T:HttpServer.Sessions.MemorySessionStore"> 4203 <member name="M:HttpServer.HttpResponse.Redirect(System.Uri)">
4098 <summary> 4204 <summary>
4099 Session store using memory for each session. 4205 Redirect client to somewhere else using the 302 status code.
4100 </summary> 4206 </summary>
4207 <param name="uri">Destination of the redirect</param>
4208 <exception cref="T:System.InvalidOperationException">If headers already been sent.</exception>
4209 <remarks>You can not do anything more with the request when a redirect have been done. This should be your last
4210 action.</remarks>
4101 </member> 4211 </member>
4102 <member name="M:HttpServer.Sessions.MemorySessionStore.#ctor"> 4212 <member name="M:HttpServer.HttpResponse.Redirect(System.String)">
4103 <summary> 4213 <summary>
4104 Initializes the class setting the expirationtimer to clean the session every minute 4214 redirect to somewhere
4105 </summary> 4215 </summary>
4216 <param name="url">where the redirect should go</param>
4217 <remarks>
4218 No body are allowed when doing redirects.
4219 </remarks>
4106 </member> 4220 </member>
4107 <member name="M:HttpServer.Sessions.MemorySessionStore.Cleanup(System.Object)"> 4221 <member name="P:HttpServer.HttpResponse.Body">
4108 <summary> 4222 <summary>
4109 Delegate for the cleanup timer 4223 The body stream is used to cache the body contents
4224 before sending everything to the client. It's the simplest
4225 way to serve documents.
4110 </summary> 4226 </summary>
4111 </member> 4227 </member>
4112 <member name="M:HttpServer.Sessions.MemorySessionStore.Create"> 4228 <member name="P:HttpServer.HttpResponse.Chunked">
4113 <summary> 4229 <summary>
4114 Creates a new http session 4230 The chunked encoding modifies the body of a message in order to
4231 transfer it as a series of chunks, each with its own size indicator,
4232 followed by an OPTIONAL trailer containing entity-header fields. This
4233 allows dynamically produced content to be transferred along with the
4234 information necessary for the recipient to verify that it has
4235 received the full message.
4115 </summary> 4236 </summary>
4116 <returns></returns>
4117 </member> 4237 </member>
4118 <member name="M:HttpServer.Sessions.MemorySessionStore.Create(System.String)"> 4238 <member name="P:HttpServer.HttpResponse.ProtocolVersion">
4119 <summary> 4239 <summary>
4120 Creates a new http session with a specific id 4240 Defines the version of the HTTP Response for applications where it's required
4241 for this to be forced.
4121 </summary> 4242 </summary>
4122 <param name="id">Id used to identify the new cookie..</param>
4123 <returns>A <see cref="T:HttpServer.Sessions.IHttpSession"/> object.</returns>
4124 <remarks>
4125 Id should be generated by the store implementation if it's null or <see cref="F:System.String.Empty"/>.
4126 </remarks>
4127 </member> 4243 </member>
4128 <member name="M:HttpServer.Sessions.MemorySessionStore.Load(System.String)"> 4244 <member name="P:HttpServer.HttpResponse.Connection">
4129 <summary> 4245 <summary>
4130 Load an existing session. 4246 Kind of connection
4131 </summary> 4247 </summary>
4132 <param name="sessionId"></param>
4133 <returns></returns>
4134 </member> 4248 </member>
4135 <member name="M:HttpServer.Sessions.MemorySessionStore.Save(HttpServer.Sessions.IHttpSession)"> 4249 <member name="P:HttpServer.HttpResponse.Encoding">
4136 <summary> 4250 <summary>
4137 Save an updated session to the store. 4251 Encoding to use when sending stuff to the client.
4138 </summary> 4252 </summary>
4139 <param name="session"></param> 4253 <remarks>Default is UTF8</remarks>
4140 </member> 4254 </member>
4141 <member name="M:HttpServer.Sessions.MemorySessionStore.AddUnused(HttpServer.Sessions.IHttpSession)"> 4255 <member name="P:HttpServer.HttpResponse.KeepAlive">
4142 <summary> 4256 <summary>
4143 We use the flyweight pattern which reuses small objects 4257 Number of seconds to keep connection alive
4144 instead of creating new each time.
4145 </summary> 4258 </summary>
4146 <param name="session">EmptyLanguageNode (unused) session that should be reused next time Create is called.</param> 4259 <remarks>Only used if Connection property is set to <see cref="F:HttpServer.ConnectionType.KeepAlive"/>.</remarks>
4147 </member> 4260 </member>
4148 <member name="M:HttpServer.Sessions.MemorySessionStore.Cleanup"> 4261 <member name="P:HttpServer.HttpResponse.Status">
4149 <summary> 4262 <summary>
4150 Remove expired sessions 4263 Status code that is sent to the client.
4151 </summary> 4264 </summary>
4265 <remarks>Default is <see cref="F:System.Net.HttpStatusCode.OK"/></remarks>
4152 </member> 4266 </member>
4153 <member name="M:HttpServer.Sessions.MemorySessionStore.Remove(System.String)"> 4267 <member name="P:HttpServer.HttpResponse.Reason">
4154 <summary> 4268 <summary>
4155 Remove a session 4269 Information about why a specific status code was used.
4156 </summary> 4270 </summary>
4157 <param name="sessionId">id of the session.</param>
4158 </member> 4271 </member>
4159 <member name="P:HttpServer.Sessions.MemorySessionStore.Item(System.String)"> 4272 <member name="P:HttpServer.HttpResponse.ContentLength">
4160 <summary> 4273 <summary>
4161 Load a session from the store 4274 Size of the body. MUST be specified before sending the header,
4275 unless property Chunked is set to true.
4162 </summary> 4276 </summary>
4163 <param name="sessionId"></param>
4164 <returns>null if session is not found.</returns>
4165 </member> 4277 </member>
4166 <member name="P:HttpServer.Sessions.MemorySessionStore.ExpireTime"> 4278 <member name="P:HttpServer.HttpResponse.ContentType">
4167 <summary> 4279 <summary>
4168 Number of minutes before a session expires. 4280 Kind of content in the body
4169 Default is 20 minutes.
4170 </summary> 4281 </summary>
4282 <remarks>Default type is "text/html"</remarks>
4171 </member> 4283 </member>
4172 <member name="T:HttpServer.Helpers.WebHelper"> 4284 <member name="P:HttpServer.HttpResponse.HeadersSent">
4173 <summary> 4285 <summary>
4174 Webhelper provides helpers for common tasks in HTML. 4286 Headers have been sent to the client-
4175 </summary> 4287 </summary>
4288 <remarks>You can not send any additional headers if they have already been sent.</remarks>
4176 </member> 4289 </member>
4177 <member name="F:HttpServer.Helpers.WebHelper.JSImplementation"> 4290 <member name="P:HttpServer.HttpResponse.Sent">
4178 <summary> 4291 <summary>
4179 Used to let the website use different javascript libraries. 4292 The whole response have been sent.
4180 Default is <see cref="T:HttpServer.Helpers.Implementations.PrototypeImp"/>
4181 </summary> 4293 </summary>
4182 </member> 4294 </member>
4183 <member name="M:HttpServer.Helpers.WebHelper.AjaxRequest(System.String,System.String,System.String[])"> 4295 <member name="P:HttpServer.HttpResponse.Cookies">
4184 <summary> 4296 <summary>
4185 Creates a link that invokes through ajax. 4297 Cookies that should be created/changed.
4186 </summary> 4298 </summary>
4187 <param name="url">url to fetch</param>
4188 <param name="title">link title</param>
4189 <param name="options">
4190 optional options in format "key, value, key, value".
4191 Javascript options starts with ':'.
4192 </param>
4193 <returns>a link tag</returns>
4194 <example>
4195 WebHelper.AjaxRequest("/users/add/", "Add user", "method:", "post", "onclick", "validate('this');");
4196 </example>
4197 </member> 4299 </member>
4198 <member name="M:HttpServer.Helpers.WebHelper.AjaxUpdater(System.String,System.String,System.String,System.String[])"> 4300 <member name="T:HttpServer.Exceptions.NotFoundException">
4199 <summary> 4301 <summary>
4200 Builds a link that updates an element with the fetched ajax content. 4302 The requested resource was not found in the web server.
4201 </summary> 4303 </summary>
4202 <param name="url">Url to fetch content from</param>
4203 <param name="title">link title</param>
4204 <param name="targetId">html element to update with the results of the ajax request.</param>
4205 <param name="options">optional options in format "key, value, key, value"</param>
4206 <returns>A link tag.</returns>
4207 </member> 4304 </member>
4208 <member name="M:HttpServer.Helpers.WebHelper.DialogLink(System.String,System.String,System.String[])"> 4305 <member name="M:HttpServer.Exceptions.NotFoundException.#ctor(System.String,System.Exception)">
4209 <summary> 4306 <summary>
4210 A link that pop ups a Dialog (overlay div) 4307 Create a new exception
4211 </summary> 4308 </summary>
4212 <param name="url">url to contents of dialog</param> 4309 <param name="message">message describing the error</param>
4213 <param name="title">link title</param> 4310 <param name="inner">inner exception</param>
4214 <param name="htmlAttributes">name/value of html attributes.</param>
4215 <returns>A "a"-tag that popups a dialog when clicked</returns>
4216 <example>
4217 WebHelper.DialogLink("/user/show/1", "show user", "onmouseover", "alert('booh!');");
4218 </example>
4219 </member> 4311 </member>
4220 <member name="M:HttpServer.Helpers.WebHelper.CreateDialog(System.String,System.String,System.String[])"> 4312 <member name="M:HttpServer.Exceptions.NotFoundException.#ctor(System.String)">
4221 <summary> 4313 <summary>
4222 Create/Open a dialog box using ajax 4314 Create a new exception
4223 </summary> 4315 </summary>
4224 <param name="url"></param> 4316 <param name="message">message describing the error</param>
4225 <param name="title"></param>
4226 <param name="parameters"></param>
4227 <returns></returns>
4228 </member> 4317 </member>
4229 <member name="M:HttpServer.Helpers.WebHelper.CloseDialog"> 4318 <member name="T:HttpServer.Sessions.MemorySessionStore">
4230 <summary> 4319 <summary>
4231 Close a javascript dialog window/div. 4320 Session store using memory for each session.
4232 </summary> 4321 </summary>
4233 <returns>javascript for closing a dialog.</returns>
4234 <see cref="M:HttpServer.Helpers.WebHelper.DialogLink(System.String,System.String,System.String[])"/>
4235 </member> 4322 </member>
4236 <member name="M:HttpServer.Helpers.WebHelper.FormStart(System.String,System.String,System.Boolean)"> 4323 <member name="T:HttpServer.Sessions.IHttpSessionStore">
4237 <summary> 4324 <summary>
4238 Create a &lt;form&gt; tag. 4325 A session store is used to store and load sessions on a media.
4326 The default implementation (<see cref="T:HttpServer.Sessions.MemorySessionStore"/>) saves/retrieves sessions from memory.
4239 </summary> 4327 </summary>
4240 <param name="name">name of form</param>
4241 <param name="action">action to invoke on submit</param>
4242 <param name="isAjax">form should be posted as ajax</param>
4243 <returns>html code</returns>
4244 <example>
4245 WebHelper.FormStart("frmLogin", "/user/login", Request.IsAjax);
4246 </example>
4247 </member> 4328 </member>
4248 <member name="M:HttpServer.Helpers.WebHelper.Link(System.String,System.String,System.String[])"> 4329 <member name="M:HttpServer.Sessions.IHttpSessionStore.Create">
4249 <summary> 4330 <summary>
4250 Create a link tag. 4331 Creates a new http session with a generated id.
4251 </summary> 4332 </summary>
4252 <param name="url">url to go to</param> 4333 <returns>A <see cref="T:HttpServer.Sessions.IHttpSession"/> object</returns>
4253 <param name="title">link title (text that is displayed)</param>
4254 <param name="htmlAttributes">html attributes, name, value, name, value</param>
4255 <returns>html code</returns>
4256 <example>
4257 WebHelper.Link("/user/show/1", "Show user", "id", "showUser", "onclick", "return confirm('Are you shure?');");
4258 </example>
4259 </member> 4334 </member>
4260 <member name="M:HttpServer.Helpers.WebHelper.BuildLink(System.String,System.String,System.String[])"> 4335 <member name="M:HttpServer.Sessions.IHttpSessionStore.Create(System.String)">
4261 <summary> 4336 <summary>
4262 Build a link 4337 Creates a new http session with a specific id
4263 </summary> 4338 </summary>
4264 <param name="url">url to go to.</param> 4339 <param name="id">Id used to identify the new cookie..</param>
4265 <param name="title">title of link (displayed text)</param> 4340 <returns>A <see cref="T:HttpServer.Sessions.IHttpSession"/> object.</returns>
4266 <param name="htmlAttributes">extra html attributes.</param> 4341 <remarks>
4267 <returns>a complete link</returns> 4342 Id should be generated by the store implementation if it's null or <see cref="F:System.String.Empty"/>.
4343 </remarks>
4268 </member> 4344 </member>
4269 <member name="M:HttpServer.Helpers.WebHelper.BuildLink(System.String,System.String,System.String[],System.String[])"> 4345 <member name="M:HttpServer.Sessions.IHttpSessionStore.Load(System.String)">
4270 <summary> 4346 <summary>
4271 Build a link 4347 Load an existing session.
4272 </summary> 4348 </summary>
4273 <param name="url">url to go to.</param> 4349 <param name="sessionId">Session id (usually retrieved from a client side cookie).</param>
4274 <param name="title">title of link (displayed text)</param> 4350 <returns>A session if found; otherwise null.</returns>
4275 <param name="htmlAttributes">extra html attributes.</param>
4276 <returns>a complete link</returns>
4277 <param name="options">more options</param>
4278 </member> 4351 </member>
4279 <member name="M:HttpServer.Helpers.WebHelper.Select(System.String,System.Collections.ICollection,HttpServer.Helpers.GetIdTitle,System.Object,System.Boolean)"> 4352 <member name="M:HttpServer.Sessions.IHttpSessionStore.Save(HttpServer.Sessions.IHttpSession)">
4280 <summary> 4353 <summary>
4281 Obsolete 4354 Save an updated session to the store.
4282 </summary> 4355 </summary>
4283 <param name="name">Obsolete</param> 4356 <param name="session">Session id (usually retrieved from a client side cookie).</param>
4284 <param name="collection">Obsolete</param> 4357 <exception cref="T:System.ArgumentException">If Id property have not been specified.</exception>
4285 <param name="getIdTitle">Obsolete</param>
4286 <param name="selectedValue">Obsolete</param>
4287 <param name="firstEmpty">Obsolete</param>
4288 <returns>Obsolete</returns>
4289 </member> 4358 </member>
4290 <member name="M:HttpServer.Helpers.WebHelper.Select(System.String,System.String,System.Collections.ICollection,HttpServer.Helpers.GetIdTitle,System.Object,System.Boolean)"> 4359 <member name="M:HttpServer.Sessions.IHttpSessionStore.AddUnused(HttpServer.Sessions.IHttpSession)">
4291 <summary> 4360 <summary>
4292 Obsolete 4361 We use the flyweight pattern which reuses small objects
4362 instead of creating new each time.
4293 </summary> 4363 </summary>
4294 <param name="name">Obsolete</param> 4364 <param name="session">Unused session that should be reused next time Create is called.</param>
4295 <param name="id">Obsolete</param>
4296 <param name="collection">Obsolete</param>
4297 <param name="getIdTitle">Obsolete</param>
4298 <param name="selectedValue">Obsolete</param>
4299 <param name="firstEmpty">Obsolete</param>
4300 <returns>Obsolete</returns>
4301 </member> 4365 </member>
4302 <member name="M:HttpServer.Helpers.WebHelper.List(System.Collections.Generic.IEnumerable{System.Object},System.String)"> 4366 <member name="M:HttpServer.Sessions.IHttpSessionStore.Cleanup">
4303 <summary> 4367 <summary>
4304 Render errors into a UL with class "errors" 4368 Remove expired sessions
4305 </summary> 4369 </summary>
4306 <param name="className">class used by UL-tag.</param>
4307 <param name="theList">items to list</param>
4308 <returns>an unordered html list.</returns>
4309 </member> 4370 </member>
4310 <member name="M:HttpServer.Helpers.WebHelper.List(System.Collections.Specialized.NameValueCollection,System.String)"> 4371 <member name="M:HttpServer.Sessions.IHttpSessionStore.Remove(System.String)">
4311 <summary> 4372 <summary>
4312 Render errors into a UL with class "errors" 4373 Remove a session
4313 </summary> 4374 </summary>
4314 <param name="className">class used by UL-tag.</param> 4375 <param name="sessionId">id of the session.</param>
4315 <param name="theList">items to list</param>
4316 <returns>an unordered html list.</returns>
4317 </member> 4376 </member>
4318 <member name="M:HttpServer.Helpers.WebHelper.Errors(System.Collections.Specialized.NameValueCollection)"> 4377 <member name="P:HttpServer.Sessions.IHttpSessionStore.Item(System.String)">
4319 <summary> 4378 <summary>
4320 Render errors into a UL with class "errors" 4379 Load a session from the store
4321 </summary> 4380 </summary>
4322 <param name="errors"></param> 4381 <param name="sessionId"></param>
4323 <returns></returns> 4382 <returns>null if session is not found.</returns>
4324 </member> 4383 </member>
4325 <member name="M:HttpServer.Helpers.WebHelper.GenerateHtmlAttributes(System.Text.StringBuilder,System.String[],System.String[])"> 4384 <member name="P:HttpServer.Sessions.IHttpSessionStore.ExpireTime">
4326 <summary> 4385 <summary>
4327 Generates a list with html attributes. 4386 Number of minutes before a session expires.
4328 </summary> 4387 </summary>
4329 <param name="sb">StringBuilder that the options should be added to.</param> 4388 <value>Default time is 20 minutes.</value>
4330 <param name="firstOptions">attributes set by user.</param>
4331 <param name="secondOptions">attributes set by any of the helper classes.</param>
4332 </member> 4389 </member>
4333 <member name="M:HttpServer.Helpers.WebHelper.GenerateHtmlAttributes(System.Text.StringBuilder,System.String[])"> 4390 <member name="M:HttpServer.Sessions.MemorySessionStore.#ctor">
4334 <summary> 4391 <summary>
4335 Generates a list with html attributes. 4392 Initializes the class setting the expirationtimer to clean the session every minute
4336 </summary> 4393 </summary>
4337 <param name="sb">StringBuilder that the options should be added to.</param>
4338 <param name="options"></param>
4339 </member> 4394 </member>
4340 <member name="T:HttpServer.Helpers.JavascriptHelperImplementation"> 4395 <member name="M:HttpServer.Sessions.MemorySessionStore.Cleanup(System.Object)">
4341 <summary> 4396 <summary>
4342 Purpose of this class is to create a javascript toolkit independent javascript helper. 4397 Delegate for the cleanup timer
4343 </summary> 4398 </summary>
4344 </member> 4399 </member>
4345 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.GenerateOptions(System.Text.StringBuilder,System.String[],System.Boolean)"> 4400 <member name="M:HttpServer.Sessions.MemorySessionStore.Create">
4346 <summary> 4401 <summary>
4347 Generates a list with JS options. 4402 Creates a new http session
4348 </summary> 4403 </summary>
4349 <param name="sb">StringBuilder that the options should be added to.</param> 4404 <returns></returns>
4350 <param name="options">the javascript options. name, value pairs. each string value should be escaped by YOU!</param>
4351 <param name="startWithComma">true if we should start with a comma.</param>
4352 </member> 4405 </member>
4353 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.RemoveJavascriptOptions(System.String[])"> 4406 <member name="M:HttpServer.Sessions.MemorySessionStore.Create(System.String)">
4354 <summary> 4407 <summary>
4355 Removes any javascript parameters from an array of parameters 4408 Creates a new http session with a specific id
4356 </summary> 4409 </summary>
4357 <param name="options">The array of parameters to remove javascript params from</param> 4410 <param name="id">Id used to identify the new cookie..</param>
4358 <returns>An array of html parameters</returns> 4411 <returns>A <see cref="T:HttpServer.Sessions.IHttpSession"/> object.</returns>
4412 <remarks>
4413 Id should be generated by the store implementation if it's null or <see cref="F:System.String.Empty"/>.
4414 </remarks>
4359 </member> 4415 </member>
4360 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.AjaxFormOnSubmit(System.String[])"> 4416 <member name="M:HttpServer.Sessions.MemorySessionStore.Load(System.String)">
4361 <summary> 4417 <summary>
4362 javascript action that should be added to the "onsubmit" event in the form tag. 4418 Load an existing session.
4363 </summary> 4419 </summary>
4420 <param name="sessionId"></param>
4364 <returns></returns> 4421 <returns></returns>
4365 <remarks>All javascript option names should end with colon.</remarks>
4366 <example>
4367 <code>
4368 JSHelper.AjaxRequest("/user/show/1", "onsuccess:", "$('userInfo').update(result);");
4369 </code>
4370 </example>
4371 </member> 4422 </member>
4372 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.AjaxRequest(System.String,System.String[])"> 4423 <member name="M:HttpServer.Sessions.MemorySessionStore.Save(HttpServer.Sessions.IHttpSession)">
4373 <summary> 4424 <summary>
4374 Requests a url through ajax 4425 Save an updated session to the store.
4375 </summary> 4426 </summary>
4376 <param name="url">url to fetch</param> 4427 <param name="session"></param>
4377 <param name="options">optional options in format "key, value, key, value", used in JS request object.</param>
4378 <returns>a link tag</returns>
4379 <remarks>All javascript option names should end with colon.</remarks>
4380 <example>
4381 <code>
4382 JSHelper.AjaxRequest("/user/show/1", "onsuccess:", "$('userInfo').update(result);");
4383 </code>
4384 </example>
4385 </member> 4428 </member>
4386 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.AjaxUpdater(System.String,System.String,System.String[])"> 4429 <member name="M:HttpServer.Sessions.MemorySessionStore.AddUnused(HttpServer.Sessions.IHttpSession)">
4387 <summary> 4430 <summary>
4388 Ajax requests that updates an element with 4431 We use the flyweight pattern which reuses small objects
4389 the fetched content 4432 instead of creating new each time.
4390 </summary> 4433 </summary>
4391 <param name="url">Url to fetch content from</param> 4434 <param name="session">EmptyLanguageNode (unused) session that should be reused next time Create is called.</param>
4392 <param name="targetId">element to update</param>
4393 <param name="options">optional options in format "key, value, key, value", used in JS updater object.</param>
4394 <returns>A link tag.</returns>
4395 <remarks>All javascript option names should end with colon.</remarks>
4396 <example>
4397 <code>
4398 JSHelper.AjaxUpdater("/user/show/1", "userInfo", "onsuccess:", "alert('Successful!');");
4399 </code>
4400 </example>
4401 </member> 4435 </member>
4402 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.DialogLink(System.String,System.String,System.String[])"> 4436 <member name="M:HttpServer.Sessions.MemorySessionStore.Cleanup">
4403 <summary> 4437 <summary>
4404 A link that pop ups a Dialog (overlay div) 4438 Remove expired sessions
4405 </summary> 4439 </summary>
4406 <param name="url">url to contents of dialog</param>
4407 <param name="title">link title</param>
4408 <returns>A "a"-tag that popups a dialog when clicked</returns>
4409 <param name="htmlAttributes">name/value of html attributes</param>
4410 <example>
4411 WebHelper.DialogLink("/user/show/1", "show user", "onmouseover", "alert('booh!');");
4412 </example>
4413 </member> 4440 </member>
4414 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.CloseDialog"> 4441 <member name="M:HttpServer.Sessions.MemorySessionStore.Remove(System.String)">
4415 <summary> 4442 <summary>
4416 Close a javascript dialog window/div. 4443 Remove a session
4417 </summary> 4444 </summary>
4418 <returns>javascript for closing a dialog.</returns> 4445 <param name="sessionId">id of the session.</param>
4419 <see cref="M:HttpServer.Helpers.JavascriptHelperImplementation.DialogLink(System.String,System.String,System.String[])"/>
4420 </member> 4446 </member>
4421 <member name="M:HttpServer.Helpers.JavascriptHelperImplementation.CreateDialog(System.String,System.String,System.String[])"> 4447 <member name="P:HttpServer.Sessions.MemorySessionStore.Item(System.String)">
4422 <summary> 4448 <summary>
4423 Creates a new modal dialog window 4449 Load a session from the store
4424 </summary> 4450 </summary>
4425 <param name="url">url to open in window.</param> 4451 <param name="sessionId"></param>
4426 <param name="title">window title (may not be supported by all js implementations)</param> 4452 <returns>null if session is not found.</returns>
4427 <param name="options"></param>
4428 <returns></returns>
4429 </member> 4453 </member>
4430 <member name="M:HttpServer.FormDecoders.HttpMultipart.ReadLine"> 4454 <member name="P:HttpServer.Sessions.MemorySessionStore.ExpireTime">
4431 <summary> 4455 <summary>
4432 4456 Number of minutes before a session expires.
4457 Default is 20 minutes.
4433 </summary> 4458 </summary>
4434 <returns></returns>
4435 <exception cref="T:System.ArgumentOutOfRangeException"></exception>
4436 <exception cref="T:System.ObjectDisposedException"></exception>
4437 </member> 4459 </member>
4438 <member name="T:HttpServer.FormDecoders.HttpMultipart.Element"> 4460 <member name="T:HttpServer.Sessions.HttpSessionClearedArgs">
4439 <summary>Represents a field in a multipart form</summary>
4440 </member>
4441 <member name="T:HttpServer.Exceptions.BadRequestException">
4442 <summary> 4461 <summary>
4443 The request could not be understood by the server due to malformed syntax. 4462 Arguments sent when a <see cref="T:HttpServer.Sessions.IHttpSession"/> is cleared
4444 The client SHOULD NOT repeat the request without modifications.
4445
4446 Text taken from: http://www.submissionchamber.com/help-guides/error-codes.php
4447 </summary> 4463 </summary>
4448 </member> 4464 </member>
4449 <member name="M:HttpServer.Exceptions.BadRequestException.#ctor(System.String)"> 4465 <member name="M:HttpServer.Sessions.HttpSessionClearedArgs.#ctor(System.Boolean)">
4450 <summary> 4466 <summary>
4451 Create a new bad request exception. 4467 Instantiates the arguments for the event
4452 </summary> 4468 </summary>
4453 <param name="errMsg">reason to why the request was bad.</param> 4469 <param name="expired">True if the session is cleared due to expiration</param>
4454 </member> 4470 </member>
4455 <member name="M:HttpServer.Exceptions.BadRequestException.#ctor(System.String,System.Exception)"> 4471 <member name="P:HttpServer.Sessions.HttpSessionClearedArgs.Expired">
4456 <summary> 4472 <summary>
4457 Create a new bad request exception. 4473 Returns true if the session is cleared due to expiration
4458 </summary> 4474 </summary>
4459 <param name="errMsg">reason to why the request was bad.</param>
4460 <param name="inner">inner exception</param>
4461 </member> 4475 </member>
4462 <member name="T:HttpServer.HttpFile"> 4476 <member name="T:HttpServer.Sessions.HttpSessionClearedHandler">
4463 <summary> 4477 <summary>
4464 Container class for posted files 4478 Delegate for when a IHttpSession is cleared
4465 </summary> 4479 </summary>
4480 <param name="session"><see cref="T:HttpServer.Sessions.IHttpSession"/> this is being cleared.</param>
4481 <param name="args">Arguments for the clearing</param>
4466 </member> 4482 </member>
4467 <member name="M:HttpServer.HttpFile.#ctor(System.String,System.String,System.String,System.String)"> 4483 <member name="T:HttpServer.RequestQueue">
4468 <summary> 4484 <summary>
4469 Creates a container for a posted file 4485 Used to queue incoming requests.
4470 </summary> 4486 </summary>
4471 <param name="name">The identifier of the post field</param>
4472 <param name="filename">The file path</param>
4473 <param name="contentType">The content type of the file</param>
4474 <param name="uploadFilename">The name of the file uploaded</param>
4475 <exception cref="T:System.ArgumentNullException">If any parameter is null or empty</exception>
4476 </member> 4487 </member>
4477 <member name="M:HttpServer.HttpFile.#ctor(System.String,System.String,System.String)"> 4488 <member name="M:HttpServer.RequestQueue.#ctor(HttpServer.ProcessRequestHandler)">
4478 <summary> 4489 <summary>
4479 Creates a container for a posted file <see cref="M:HttpServer.HttpFile.#ctor(System.String,System.String,System.String,System.String)"/> 4490 Initializes a new instance of the <see cref="T:HttpServer.RequestQueue"/> class.
4480 </summary> 4491 </summary>
4481 <exception cref="T:System.ArgumentNullException">If any parameter is null or empty</exception> 4492 <param name="handler">Called when a request should be processed.</param>
4482 </member>
4483 <member name="M:HttpServer.HttpFile.Finalize">
4484 <summary>Destructor disposing the file</summary>
4485 </member> 4493 </member>
4486 <member name="M:HttpServer.HttpFile.Dispose(System.Boolean)"> 4494 <member name="M:HttpServer.RequestQueue.QueueThread">
4487 <summary> 4495 <summary>
4488 Deletes the temporary file 4496 Used to process queued requests.
4489 </summary> 4497 </summary>
4490 <param name="disposing">True if manual dispose</param>
4491 </member> 4498 </member>
4492 <member name="M:HttpServer.HttpFile.Dispose"> 4499 <member name="P:HttpServer.RequestQueue.MaxRequestCount">
4493 <summary> 4500 <summary>
4494 Disposing interface, cleans up managed resources (the temporary file) and suppresses finalization 4501 Gets or sets maximum number of allowed simultaneous requests.
4495 </summary> 4502 </summary>
4496 </member> 4503 </member>
4497 <member name="P:HttpServer.HttpFile.Name"> 4504 <member name="P:HttpServer.RequestQueue.MaxQueueSize">
4498 <summary> 4505 <summary>
4499 The name/id of the file 4506 Gets or sets maximum number of requests queuing to be handled.
4500 </summary> 4507 </summary>
4501 </member> 4508 </member>
4502 <member name="P:HttpServer.HttpFile.Filename"> 4509 <member name="P:HttpServer.RequestQueue.CurrentRequestCount">
4503 <summary> 4510 <summary>
4504 The full file path 4511 Specifies how many requests the HTTP server is currently processing.
4505 </summary> 4512 </summary>
4506 </member> 4513 </member>
4507 <member name="P:HttpServer.HttpFile.UploadFilename"> 4514 <member name="T:HttpServer.RequestQueue.QueueItem">
4508 <summary> 4515 <summary>
4509 The name of the uploaded file 4516 Used two queue incoming requests to avoid
4517 thread starvation.
4510 </summary> 4518 </summary>
4511 </member> 4519 </member>
4512 <member name="P:HttpServer.HttpFile.ContentType"> 4520 <member name="T:HttpServer.ProcessRequestHandler">
4513 <summary> 4521 <summary>
4514 The type of file 4522 Method used to process a queued request
4515 </summary> 4523 </summary>
4524 <param name="context">Context that the request was received from.</param>
4525 <param name="request">Request to process.</param>
4516 </member> 4526 </member>
4517 <member name="T:HttpServer.Helpers.JSHelper"> 4527 <member name="T:HttpServer.Parser.HeaderEventArgs">
4518 <summary> 4528 <summary>
4519 Will contain helper functions for javascript. 4529 Event arguments used when a new header have been parsed.
4520 </summary> 4530 </summary>
4521 </member> 4531 </member>
4522 <member name="M:HttpServer.Helpers.JSHelper.AjaxRequest(System.String,System.String[])"> 4532 <member name="M:HttpServer.Parser.HeaderEventArgs.#ctor(System.String,System.String)">
4523 <summary> 4533 <summary>
4524 Requests a url through ajax 4534 Initializes a new instance of the <see cref="T:HttpServer.Parser.HeaderEventArgs"/> class.
4525 </summary> 4535 </summary>
4526 <param name="url">url to fetch. Url is NOT enclosed in quotes by the implementation. You need to do that yourself.</param> 4536 <param name="name">Name of header.</param>
4527 <param name="options">optional options in format "key, value, key, value", used in JS request object. All keys should end with colon.</param> 4537 <param name="value">Header value.</param>
4528 <returns>a link tag</returns>
4529 <remarks>onclick attribute is used by this method.</remarks>
4530 <example>
4531 <code>
4532 // plain text
4533 JSHelper.AjaxRequest("'/user/show/1'");
4534
4535 // ajax request using this.href
4536 string link = "&lt;a href=\"/user/call/1\" onclick=\"" + JSHelper.AjaxRequest("this.href") + "/&lt;call user&lt;/a&gt;";
4537 </code>
4538 </example>
4539 </member> 4538 </member>
4540 <member name="M:HttpServer.Helpers.JSHelper.AjaxUpdater(System.String,System.String,System.String[])"> 4539 <member name="M:HttpServer.Parser.HeaderEventArgs.#ctor">
4541 <summary> 4540 <summary>
4542 Ajax requests that updates an element with 4541 Initializes a new instance of the <see cref="T:HttpServer.Parser.HeaderEventArgs"/> class.
4543 the fetched content
4544 </summary> 4542 </summary>
4545 <param name="url">url to fetch. Url is NOT enclosed in quotes by the implementation. You need to do that yourself.</param>
4546 <param name="targetId">element to update</param>
4547 <param name="options">options in format "key, value, key, value". All keys should end with colon.</param>
4548 <returns>A link tag.</returns>
4549 <example>
4550 <code>
4551 JSHelper.AjaxUpdater("'/user/show/1'", "user", "onsuccess:", "alert('hello');", "asynchronous:", "true");
4552 </code>
4553 </example>
4554 </member> 4543 </member>
4555 <member name="M:HttpServer.Helpers.JSHelper.CreateDialog(System.String,System.String,System.String[])"> 4544 <member name="P:HttpServer.Parser.HeaderEventArgs.Name">
4556 <summary> 4545 <summary>
4557 Opens contents in a dialog window. 4546 Gets or sets header name.
4558 </summary> 4547 </summary>
4559 <param name="url">url to contents of dialog</param>
4560 <param name="title">link title</param>
4561 <param name="options">name, value, name, value, all parameter names should end with colon.</param>
4562 </member> 4548 </member>
4563 <member name="M:HttpServer.Helpers.JSHelper.CloseDialog"> 4549 <member name="P:HttpServer.Parser.HeaderEventArgs.Value">
4564 <summary> 4550 <summary>
4565 Close a javascript dialog window/div. 4551 Gets or sets header value.
4566 </summary> 4552 </summary>
4567 <returns>javascript for closing a dialog.</returns>
4568 <see cref="M:HttpServer.Helpers.JSHelper.CreateDialog(System.String,System.String,System.String[])"/>
4569 </member> 4553 </member>
4570 <member name="T:HttpServer.HttpRequest"> 4554 <member name="T:HttpServer.HttpRequest">
4571 <summary> 4555 <summary>
@@ -4743,34 +4727,108 @@
4743 Gets cookies that was sent with the request. 4727 Gets cookies that was sent with the request.
4744 </summary> 4728 </summary>
4745 </member> 4729 </member>
4746 <member name="T:HttpServer.HttpModules.WebSiteModule"> 4730 <member name="M:HttpServer.ComponentProvider.AddInstance``1(System.Object)">
4747 <summary> 4731 <summary>
4748 The website module let's you handle multiple websites in the same server. 4732 Add a component instance
4749 It uses the "Host" header to check which site you want.
4750 </summary> 4733 </summary>
4751 <remarks>It's recommended that you do not 4734 <typeparam name="T">Interface type</typeparam>
4752 add any other modules to HttpServer if you are using the website module. Instead, 4735 <param name="instance">Instance to add</param>
4753 add all wanted modules to each website.</remarks>
4754 </member> 4736 </member>
4755 <member name="M:HttpServer.HttpModules.WebSiteModule.#ctor(System.String,System.String)"> 4737 <member name="M:HttpServer.ComponentProvider.Get``1">
4756 <summary> 4738 <summary>
4757 4739 Get a component.
4758 </summary> 4740 </summary>
4759 <param name="host">domain name that should be handled.</param> 4741 <typeparam name="T">Interface type</typeparam>
4760 <param name="name"></param> 4742 <returns>Component if registered, otherwise null.</returns>
4743 <remarks>
4744 Component will get created if needed.
4745 </remarks>
4761 </member> 4746 </member>
4762 <member name="M:HttpServer.HttpModules.WebSiteModule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)"> 4747 <member name="M:HttpServer.ComponentProvider.Create(HttpServer.ComponentProvider.TypeInformation)">
4748 <exception cref="T:System.InvalidOperationException">If instance cannot be created.</exception>
4749 </member>
4750 <member name="M:HttpServer.ComponentProvider.Contains(System.Type)">
4763 <summary> 4751 <summary>
4764 Method that process the url 4752 Checks if the specified component interface have been added.
4765 </summary> 4753 </summary>
4766 <param name="request">Information sent by the browser about the request</param> 4754 <param name="interfaceType"></param>
4767 <param name="response">Information that is being sent back to the client.</param> 4755 <returns>true if found; otherwise false.</returns>
4768 <param name="session">Session used to </param>
4769 </member> 4756 </member>
4770 <member name="P:HttpServer.HttpModules.WebSiteModule.SiteName"> 4757 <member name="M:HttpServer.ComponentProvider.Add``2">
4771 <summary> 4758 <summary>
4772 Name of site. 4759 Add a component.
4760 </summary>
4761 <typeparam name="InterfaceType">Type being requested.</typeparam>
4762 <typeparam name="InstanceType">Type being created.</typeparam>
4763 <exception cref="T:System.InvalidOperationException">Type have already been mapped.</exception>
4764 </member>
4765 <member name="T:HttpServer.Rules.RegexRedirectRule">
4766 <summary>
4767 Class to make dynamic binding of redirects. Instead of having to specify a number of similar redirect rules
4768 a regular expression can be used to identify redirect URLs and their targets.
4769 </summary>
4770 <example>
4771 <![CDATA[
4772 new RegexRedirectRule("/(?<target>[a-z0-9]+)", "/users/${target}?find=true", RegexOptions.IgnoreCase)
4773 ]]>
4774 </example>
4775 </member>
4776 <member name="M:HttpServer.Rules.RegexRedirectRule.#ctor(System.String,System.String)">
4777 <summary>
4778 Initializes a new instance of the <see cref="T:HttpServer.Rules.RegexRedirectRule"/> class.
4779 </summary>
4780 <param name="fromUrlExpression">Expression to match URL</param>
4781 <param name="toUrlExpression">Expression to generate URL</param>
4782 <example>
4783 <![CDATA[
4784 server.Add(new RegexRedirectRule("/(?<first>[a-zA-Z0-9]+)", "/user/${first}"));
4785 Result of ie. /employee1 will then be /user/employee1
4786 ]]>
4787 </example>
4788 </member>
4789 <member name="M:HttpServer.Rules.RegexRedirectRule.#ctor(System.String,System.String,System.Text.RegularExpressions.RegexOptions)">
4790 <summary>
4791 Initializes a new instance of the <see cref="T:HttpServer.Rules.RegexRedirectRule"/> class.
4792 </summary>
4793 <param name="fromUrlExpression">Expression to match URL</param>
4794 <param name="toUrlExpression">Expression to generate URL</param>
4795 <param name="options">Regular expression options to use, can be null</param>
4796 <example>
4797 <![CDATA[
4798 server.Add(new RegexRedirectRule("/(?<first>[a-zA-Z0-9]+)", "/user/{first}", RegexOptions.IgnoreCase));
4799 Result of ie. /employee1 will then be /user/employee1
4800 ]]>
4801 </example>
4802 </member>
4803 <member name="M:HttpServer.Rules.RegexRedirectRule.#ctor(System.String,System.String,System.Text.RegularExpressions.RegexOptions,System.Boolean)">
4804 <summary>
4805 Initializes a new instance of the <see cref="T:HttpServer.Rules.RegexRedirectRule"/> class.
4806 </summary>
4807 <param name="fromUrlExpression">Expression to match URL</param>
4808 <param name="toUrlExpression">Expression to generate URL</param>
4809 <param name="options">Regular expression options to apply</param>
4810 <param name="shouldRedirect"><c>true</c> if request should be redirected, <c>false</c> if the request URI should be replaced.</param>
4811 <example>
4812 <![CDATA[
4813 server.Add(new RegexRedirectRule("/(?<first>[a-zA-Z0-9]+)", "/user/${first}", RegexOptions.None));
4814 Result of ie. /employee1 will then be /user/employee1
4815 ]]>
4816 </example>
4817 <exception cref="T:System.ArgumentNullException">Argument is null.</exception>
4818 <seealso cref="P:HttpServer.Rules.RedirectRule.ShouldRedirect"/>
4819 </member>
4820 <member name="M:HttpServer.Rules.RegexRedirectRule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse)">
4821 <summary>
4822 Process the incoming request.
4773 </summary> 4823 </summary>
4824 <param name="request">incoming HTTP request</param>
4825 <param name="response">outgoing HTTP response</param>
4826 <returns>true if response should be sent to the browser directly (no other rules or modules will be processed).</returns>
4827 <remarks>
4828 returning true means that no modules will get the request. Returning true is typically being done
4829 for redirects.
4830 </remarks>
4831 <exception cref="T:System.ArgumentNullException">If request or response is null</exception>
4774 </member> 4832 </member>
4775 <member name="T:HttpServer.Helpers.ResourceInfo"> 4833 <member name="T:HttpServer.Helpers.ResourceInfo">
4776 <summary> 4834 <summary>
@@ -4812,30 +4870,6 @@
4812 <member name="P:HttpServer.Helpers.ResourceInfo.ResourceName"> 4870 <member name="P:HttpServer.Helpers.ResourceInfo.ResourceName">
4813 <summary>Retrieves the full path name to the resource file</summary> 4871 <summary>Retrieves the full path name to the resource file</summary>
4814 </member> 4872 </member>
4815 <member name="T:HttpServer.RequestParserFactory">
4816 <summary>
4817 Creates request parsers when needed.
4818 </summary>
4819 </member>
4820 <member name="T:HttpServer.IRequestParserFactory">
4821 <summary>
4822 Creates request parsers when needed.
4823 </summary>
4824 </member>
4825 <member name="M:HttpServer.IRequestParserFactory.CreateParser(HttpServer.ILogWriter)">
4826 <summary>
4827 Create a new request parser.
4828 </summary>
4829 <param name="logWriter">Used when logging should be enabled.</param>
4830 <returns>A new request parser.</returns>
4831 </member>
4832 <member name="M:HttpServer.RequestParserFactory.CreateParser(HttpServer.ILogWriter)">
4833 <summary>
4834 Create a new request parser.
4835 </summary>
4836 <param name="logWriter">Used when logging should be enabled.</param>
4837 <returns>A new request parser.</returns>
4838 </member>
4839 <member name="T:HttpServer.Authentication.BasicAuthentication"> 4873 <member name="T:HttpServer.Authentication.BasicAuthentication">
4840 <summary> 4874 <summary>
4841 The "basic" authentication scheme is based on the model that the 4875 The "basic" authentication scheme is based on the model that the
@@ -4921,533 +4955,499 @@
4921 Adding bytes to body 4955 Adding bytes to body
4922 </summary> 4956 </summary>
4923 </member> 4957 </member>
4924 <member name="T:HttpServer.FormDecoders.XmlDecoder"> 4958 <member name="T:HttpServer.Helpers.JSHelper">
4925 <summary>
4926 This decoder converts XML documents to form items.
4927 Each element becomes a subitem in the form, and each attribute becomes an item.
4928 </summary>
4929 <example>
4930 // xml: <hello id="1">something<world id="2">data</world></hello>
4931 // result:
4932 // form["hello"].Value = "something"
4933 // form["hello"]["id"].Value = 1
4934 // form["hello"]["world]["id"].Value = 1
4935 // form["hello"]["world"].Value = "data"
4936 </example>
4937 <remarks>
4938 The original xml document is stored in form["__xml__"].Value.
4939 </remarks>
4940 </member>
4941 <member name="M:HttpServer.FormDecoders.XmlDecoder.Decode(System.IO.Stream,System.String,System.Text.Encoding)">
4942 <summary>
4943
4944 </summary>
4945 <param name="stream">Stream containing the content</param>
4946 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case</param>
4947 <param name="encoding">Stream encoding</param>
4948 Note: contentType and encoding are not used?
4949 <returns>A http form, or null if content could not be parsed.</returns>
4950 <exception cref="T:System.IO.InvalidDataException"></exception>
4951 </member>
4952 <member name="M:HttpServer.FormDecoders.XmlDecoder.TraverseNode(HttpServer.IHttpInput,System.Xml.XmlNode)">
4953 <summary>
4954 Recursive function that will go through an xml element and store it's content
4955 to the form item.
4956 </summary>
4957 <param name="item">(parent) Item in form that content should be added to.</param>
4958 <param name="node">Node that should be parsed.</param>
4959 </member>
4960 <member name="M:HttpServer.FormDecoders.XmlDecoder.CanParse(System.String)">
4961 <summary>
4962 Checks if the decoder can handle the mime type
4963 </summary>
4964 <param name="contentType">Content type (with any additional info like boundry). Content type is always supplied in lower case.</param>
4965 <returns>True if the decoder can parse the specified content type</returns>
4966 </member>
4967 <member name="T:HttpServer.ResponseCookies">
4968 <summary>
4969 Cookies that should be set.
4970 </summary>
4971 </member>
4972 <member name="M:HttpServer.ResponseCookies.Add(HttpServer.ResponseCookie)">
4973 <summary> 4959 <summary>
4974 Adds a cookie in the collection. 4960 Will contain helper functions for javascript.
4975 </summary> 4961 </summary>
4976 <param name="cookie">cookie to add</param>
4977 <exception cref="T:System.ArgumentNullException">cookie is null</exception>
4978 </member> 4962 </member>
4979 <member name="M:HttpServer.ResponseCookies.Add(HttpServer.RequestCookie,System.DateTime)"> 4963 <member name="M:HttpServer.Helpers.JSHelper.AjaxRequest(System.String,System.String[])">
4980 <summary> 4964 <summary>
4981 Copy a request cookie 4965 Requests a url through ajax
4982 </summary> 4966 </summary>
4983 <param name="cookie"></param> 4967 <param name="url">url to fetch. Url is NOT enclosed in quotes by the implementation. You need to do that yourself.</param>
4984 <param name="expires">When the cookie should expire</param> 4968 <param name="options">optional options in format "key, value, key, value", used in JS request object. All keys should end with colon.</param>
4969 <returns>a link tag</returns>
4970 <remarks>onclick attribute is used by this method.</remarks>
4971 <example>
4972 <code>
4973 // plain text
4974 JSHelper.AjaxRequest("'/user/show/1'");
4975
4976 // ajax request using this.href
4977 string link = "&lt;a href=\"/user/call/1\" onclick=\"" + JSHelper.AjaxRequest("this.href") + "/&lt;call user&lt;/a&gt;";
4978 </code>
4979 </example>
4985 </member> 4980 </member>
4986 <member name="M:HttpServer.ResponseCookies.GetEnumerator"> 4981 <member name="M:HttpServer.Helpers.JSHelper.AjaxUpdater(System.String,System.String,System.String[])">
4987 <summary> 4982 <summary>
4988 Gets a collection enumerator on the cookie list. 4983 Ajax requests that updates an element with
4984 the fetched content
4989 </summary> 4985 </summary>
4990 <returns>collection enumerator</returns> 4986 <param name="url">url to fetch. Url is NOT enclosed in quotes by the implementation. You need to do that yourself.</param>
4987 <param name="targetId">element to update</param>
4988 <param name="options">options in format "key, value, key, value". All keys should end with colon.</param>
4989 <returns>A link tag.</returns>
4990 <example>
4991 <code>
4992 JSHelper.AjaxUpdater("'/user/show/1'", "user", "onsuccess:", "alert('hello');", "asynchronous:", "true");
4993 </code>
4994 </example>
4991 </member> 4995 </member>
4992 <member name="M:HttpServer.ResponseCookies.Clear"> 4996 <member name="M:HttpServer.Helpers.JSHelper.CreateDialog(System.String,System.String,System.String[])">
4993 <summary> 4997 <summary>
4994 Remove all cookies 4998 Opens contents in a dialog window.
4995 </summary> 4999 </summary>
5000 <param name="url">url to contents of dialog</param>
5001 <param name="title">link title</param>
5002 <param name="options">name, value, name, value, all parameter names should end with colon.</param>
4996 </member> 5003 </member>
4997 <member name="M:HttpServer.ResponseCookies.System#Collections#Generic#IEnumerable{HttpServer#ResponseCookie}#GetEnumerator"> 5004 <member name="M:HttpServer.Helpers.JSHelper.CloseDialog">
4998 <summary> 5005 <summary>
4999 Returns an enumerator that iterates through the collection. 5006 Close a javascript dialog window/div.
5000 </summary> 5007 </summary>
5001 5008 <returns>javascript for closing a dialog.</returns>
5002 <returns> 5009 <see cref="M:HttpServer.Helpers.JSHelper.CreateDialog(System.String,System.String,System.String[])"/>
5003 A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> that can be used to iterate through the collection.
5004 </returns>
5005 <filterpriority>1</filterpriority>
5006 </member> 5010 </member>
5007 <member name="P:HttpServer.ResponseCookies.Count"> 5011 <member name="T:HttpServer.ContentType">
5008 <summary> 5012 <summary>
5009 Gets the count of cookies in the collection. 5013 Lists content type mime types.
5010 </summary> 5014 </summary>
5011 </member> 5015 </member>
5012 <member name="P:HttpServer.ResponseCookies.Item(System.String)"> 5016 <member name="F:HttpServer.ContentType.Text">
5013 <summary> 5017 <summary>
5014 Gets the cookie of a given identifier (null if not existing). 5018 text/plain
5015 </summary> 5019 </summary>
5016 </member> 5020 </member>
5017 <member name="T:HttpServer.RequestCookies"> 5021 <member name="F:HttpServer.ContentType.Html">
5018 <summary> 5022 <summary>
5019 This class is created as a wrapper, since there are two different cookie types in .Net (Cookie and HttpCookie). 5023 text/haml
5020 The framework might switch class in the future and we dont want to have to replace all instances
5021 </summary> 5024 </summary>
5022 </member> 5025 </member>
5023 <member name="M:HttpServer.RequestCookies.#ctor(System.String)"> 5026 <member name="F:HttpServer.ContentType.Javascript">
5024 <summary> 5027 <summary>
5025 Let's copy all the cookies. 5028 content type for javascript documents = application/javascript
5026 </summary> 5029 </summary>
5027 <param name="cookies">value from cookie header.</param> 5030 <remarks>
5031 <para>
5032 RFC 4329 states that text/javascript have been superseeded by
5033 application/javascript. You might still want to check browser versions
5034 since older ones do not support application/javascript.
5035 </para>
5036 <para>Browser support: http://krijnhoetmer.nl/stuff/javascript/mime-types/</para>
5037 </remarks>
5028 </member> 5038 </member>
5029 <member name="M:HttpServer.RequestCookies.Add(HttpServer.RequestCookie)"> 5039 <member name="F:HttpServer.ContentType.Xml">
5030 <summary> 5040 <summary>
5031 Adds a cookie in the collection. 5041 text/xml
5032 </summary> 5042 </summary>
5033 <param name="cookie">cookie to add</param>
5034 <exception cref="T:System.ArgumentNullException">cookie is null</exception>
5035 </member> 5043 </member>
5036 <member name="M:HttpServer.RequestCookies.GetEnumerator"> 5044 <member name="T:HttpServer.ContentTypes">
5037 <summary> 5045 <summary>
5038 Gets a collection enumerator on the cookie list. 5046 A list of content types
5039 </summary> 5047 </summary>
5040 <returns>collection enumerator</returns>
5041 </member> 5048 </member>
5042 <member name="M:HttpServer.RequestCookies.Clear"> 5049 <member name="M:HttpServer.ContentTypes.#ctor(System.String)">
5043 <summary> 5050 <summary>
5044 Remove all cookies. 5051
5045 </summary> 5052 </summary>
5053 <param name="types">Semicolon separated content types.</param>
5046 </member> 5054 </member>
5047 <member name="M:HttpServer.RequestCookies.System#Collections#Generic#IEnumerable{HttpServer#RequestCookie}#GetEnumerator"> 5055 <member name="M:HttpServer.ContentTypes.GetEnumerator">
5048 <summary> 5056 <summary>
5049 Returns an enumerator that iterates through the collection. 5057 Returns an enumerator that iterates through a collection.
5050 </summary> 5058 </summary>
5051
5052 <returns> 5059 <returns>
5053 A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> that can be used to iterate through the collection. 5060 An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
5054 </returns> 5061 </returns>
5055 <filterpriority>1</filterpriority>
5056 </member> 5062 </member>
5057 <member name="M:HttpServer.RequestCookies.Remove(System.String)"> 5063 <member name="M:HttpServer.ContentTypes.Contains(System.String)">
5058 <summary>
5059 Remove a cookie from the collection.
5060 </summary>
5061 <param name="cookieName">Name of cookie.</param>
5062 </member>
5063 <member name="P:HttpServer.RequestCookies.Count">
5064 <summary>
5065 Gets the count of cookies in the collection.
5066 </summary>
5067 </member>
5068 <member name="P:HttpServer.RequestCookies.Item(System.String)">
5069 <summary> 5064 <summary>
5070 Gets the cookie of a given identifier (null if not existing). 5065 Searches for the specified type
5071 </summary> 5066 </summary>
5067 <param name="type">Can also be a part of a type (searching for "xml" would return true for "application/xml").</param>
5068 <returns>true if type was found.</returns>
5072 </member> 5069 </member>
5073 <member name="T:HttpServer.HttpListener"> 5070 <member name="P:HttpServer.ContentTypes.First">
5074 <summary> 5071 <summary>
5075 New implementation of the HTTP listener. 5072 Get this first content type.
5076 </summary> 5073 </summary>
5077 <remarks>
5078 Use the <c>Create</c> methods to create a default listener.
5079 </remarks>
5080 </member> 5074 </member>
5081 <member name="M:HttpServer.HttpListener.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory)"> 5075 <member name="P:HttpServer.ContentTypes.Item(System.String)">
5082 <summary> 5076 <summary>
5083 Initializes a new instance of the <see cref="T:HttpServer.HttpListener"/> class. 5077 Fetch a content type
5084 </summary> 5078 </summary>
5085 <param name="address">IP Address to accept connections on</param> 5079 <param name="type">Part of type ("xml" would return "application/xml")</param>
5086 <param name="port">TCP Port to listen on, default HTTP port is 80.</param> 5080 <returns></returns>
5087 <param name="factory">Factory used to create <see cref="T:HttpServer.IHttpClientContext"/>es.</param> 5081 <remarks>All content types are in lower case.</remarks>
5088 <exception cref="T:System.ArgumentNullException"><c>address</c> is null.</exception>
5089 <exception cref="T:System.ArgumentException">Port must be a positive number.</exception>
5090 </member> 5082 </member>
5091 <member name="M:HttpServer.HttpListener.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory,System.Security.Cryptography.X509Certificates.X509Certificate)"> 5083 <member name="T:HttpServer.RequestParserFactory">
5092 <summary> 5084 <summary>
5093 Initializes a new instance of the <see cref="T:HttpServer.HttpListener"/> class. 5085 Creates request parsers when needed.
5094 </summary> 5086 </summary>
5095 <param name="address">The address.</param>
5096 <param name="port">The port.</param>
5097 <param name="factory">The factory.</param>
5098 <param name="certificate">The certificate.</param>
5099 </member> 5087 </member>
5100 <member name="M:HttpServer.HttpListener.#ctor(System.Net.IPAddress,System.Int32,HttpServer.IHttpContextFactory,System.Security.Cryptography.X509Certificates.X509Certificate,System.Security.Authentication.SslProtocols)"> 5088 <member name="T:HttpServer.IRequestParserFactory">
5101 <summary> 5089 <summary>
5102 Initializes a new instance of the <see cref="T:HttpServer.HttpListener"/> class. 5090 Creates request parsers when needed.
5103 </summary> 5091 </summary>
5104 <param name="address">The address.</param>
5105 <param name="port">The port.</param>
5106 <param name="factory">The factory.</param>
5107 <param name="certificate">The certificate.</param>
5108 <param name="protocol">The protocol.</param>
5109 </member> 5092 </member>
5110 <member name="M:HttpServer.HttpListener.Create(System.Net.IPAddress,System.Int32)"> 5093 <member name="M:HttpServer.IRequestParserFactory.CreateParser(HttpServer.ILogWriter)">
5111 <summary> 5094 <summary>
5112 Creates a new <see cref="T:HttpServer.HttpListener"/> instance with default factories. 5095 Create a new request parser.
5113 </summary> 5096 </summary>
5114 <param name="address">Address that the listener should accept connections on.</param> 5097 <param name="logWriter">Used when logging should be enabled.</param>
5115 <param name="port">Port that listener should accept connections on.</param> 5098 <returns>A new request parser.</returns>
5116 <returns>Created HTTP listener.</returns>
5117 </member> 5099 </member>
5118 <member name="M:HttpServer.HttpListener.Create(System.Net.IPAddress,System.Int32,System.Security.Cryptography.X509Certificates.X509Certificate)"> 5100 <member name="M:HttpServer.RequestParserFactory.CreateParser(HttpServer.ILogWriter)">
5119 <summary> 5101 <summary>
5120 Creates a new <see cref="T:HttpServer.HttpListener"/> instance with default factories. 5102 Create a new request parser.
5121 </summary> 5103 </summary>
5122 <param name="address">Address that the listener should accept connections on.</param> 5104 <param name="logWriter">Used when logging should be enabled.</param>
5123 <param name="port">Port that listener should accept connections on.</param> 5105 <returns>A new request parser.</returns>
5124 <param name="certificate">Certificate to use</param>
5125 <returns>Created HTTP listener.</returns>
5126 </member> 5106 </member>
5127 <member name="M:HttpServer.HttpListener.Create(System.Net.IPAddress,System.Int32,System.Security.Cryptography.X509Certificates.X509Certificate,System.Security.Authentication.SslProtocols)"> 5107 <member name="T:HttpServer.Exceptions.UnauthorizedException">
5128 <summary> 5108 <summary>
5129 Creates a new <see cref="T:HttpServer.HttpListener"/> instance with default factories. 5109 The request requires user authentication. The response MUST include a
5110 WWW-Authenticate header field (section 14.47) containing a challenge
5111 applicable to the requested resource.
5112
5113 The client MAY repeat the request with a suitable Authorization header
5114 field (section 14.8). If the request already included Authorization
5115 credentials, then the 401 response indicates that authorization has been
5116 refused for those credentials. If the 401 response contains the same challenge
5117 as the prior response, and the user agent has already attempted authentication
5118 at least once, then the user SHOULD be presented the entity that was given in the response,
5119 since that entity might include relevant diagnostic information.
5120
5121 HTTP access authentication is explained in rfc2617:
5122 http://www.ietf.org/rfc/rfc2617.txt
5123
5124 (description is taken from
5125 http://www.submissionchamber.com/help-guides/error-codes.php#sec10.4.2)
5130 </summary> 5126 </summary>
5131 <param name="address">Address that the listener should accept connections on.</param>
5132 <param name="port">Port that listener should accept connections on.</param>
5133 <param name="certificate">Certificate to use</param>
5134 <param name="protocol">which HTTPS protocol to use, default is TLS.</param>
5135 <returns>Created HTTP listener.</returns>
5136 </member> 5127 </member>
5137 <member name="M:HttpServer.HttpListener.OnAcceptingSocket(System.Net.Sockets.Socket)"> 5128 <member name="M:HttpServer.Exceptions.UnauthorizedException.#ctor">
5138 <summary> 5129 <summary>
5139 Can be used to create filtering of new connections. 5130 Create a new unauhtorized exception.
5140 </summary> 5131 </summary>
5141 <param name="socket">Accepted socket</param> 5132 <seealso cref="T:HttpServer.Exceptions.UnauthorizedException"/>
5142 <returns>
5143 true if connection can be accepted; otherwise false.
5144 </returns>
5145 </member> 5133 </member>
5146 <member name="E:HttpServer.HttpListener.Accepted"> 5134 <member name="M:HttpServer.Exceptions.UnauthorizedException.#ctor(System.String,System.Exception)">
5147 <summary> 5135 <summary>
5148 A client have been accepted, but not handled, by the listener. 5136 Create a new unauhtorized exception.
5149 </summary> 5137 </summary>
5138 <param name="message">reason to why the request was unauthorized.</param>
5139 <param name="inner">inner exception</param>
5150 </member> 5140 </member>
5151 <member name="T:HttpServer.HttpHelper"> 5141 <member name="M:HttpServer.Exceptions.UnauthorizedException.#ctor(System.String)">
5152 <summary> 5142 <summary>
5153 Generic helper functions for HTTP 5143 Create a new unauhtorized exception.
5154 </summary> 5144 </summary>
5145 <param name="message">reason to why the request was unauthorized.</param>
5155 </member> 5146 </member>
5156 <member name="F:HttpServer.HttpHelper.HTTP10"> 5147 <member name="T:HttpServer.HttpModules.FileModule">
5157 <summary> 5148 <summary>
5158 Version string for HTTP v1.0 5149 The purpose of this module is to serve files.
5159 </summary> 5150 </summary>
5160 </member> 5151 </member>
5161 <member name="F:HttpServer.HttpHelper.HTTP11"> 5152 <member name="M:HttpServer.HttpModules.FileModule.#ctor(System.String,System.String,System.Boolean)">
5162 <summary> 5153 <summary>
5163 Version string for HTTP v1.1 5154 Initializes a new instance of the <see cref="T:HttpServer.HttpModules.FileModule"/> class.
5164 </summary> 5155 </summary>
5156 <param name="baseUri">Uri to serve, for instance "/files/"</param>
5157 <param name="basePath">Path on hard drive where we should start looking for files</param>
5158 <param name="useLastModifiedHeader">If true a Last-Modifed header will be sent upon requests urging web browser to cache files</param>
5165 </member> 5159 </member>
5166 <member name="F:HttpServer.HttpHelper.EmptyUri"> 5160 <member name="M:HttpServer.HttpModules.FileModule.#ctor(System.String,System.String)">
5167 <summary> 5161 <summary>
5168 An empty URI 5162 Initializes a new instance of the <see cref="T:HttpServer.HttpModules.FileModule"/> class.
5169 </summary> 5163 </summary>
5164 <param name="baseUri">Uri to serve, for instance "/files/"</param>
5165 <param name="basePath">Path on hard drive where we should start looking for files</param>
5170 </member> 5166 </member>
5171 <member name="M:HttpServer.HttpHelper.ParseQueryString(System.String)"> 5167 <member name="M:HttpServer.HttpModules.FileModule.AddDefaultMimeTypes">
5172 <summary> 5168 <summary>
5173 Parses a query string. 5169 Mimtypes that this class can handle per default
5174 </summary> 5170 </summary>
5175 <param name="queryString">Query string (URI encoded)</param>
5176 <returns>A <see cref="T:HttpServer.HttpInput"/> object if successful; otherwise <see cref="F:HttpServer.HttpInput.Empty"/></returns>
5177 <exception cref="T:System.ArgumentNullException"><c>queryString</c> is null.</exception>
5178 <exception cref="T:System.FormatException">If string cannot be parsed.</exception>
5179 </member> 5171 </member>
5180 <member name="T:HttpServer.HttpModules.ReverseProxyModule"> 5172 <member name="M:HttpServer.HttpModules.FileModule.CanHandle(System.Uri)">
5181 <summary> 5173 <summary>
5182 A reverse proxy are used to act as a bridge between local (protected/hidden) websites 5174 Determines if the request should be handled by this module.
5183 and public clients. 5175 Invoked by the <see cref="T:HttpServer.HttpServer"/>
5184
5185 A typical usage is to allow web servers on non standard ports to still be available
5186 to the public clients, or allow web servers on private ips to be available.
5187 </summary> 5176 </summary>
5177 <param name="uri"></param>
5178 <returns>true if this module should handle it.</returns>
5188 </member> 5179 </member>
5189 <member name="M:HttpServer.HttpModules.ReverseProxyModule.#ctor(System.String,System.String)"> 5180 <member name="M:HttpServer.HttpModules.FileModule.GetPath(System.Uri)">
5190 <summary> 5181 <exception cref="T:HttpServer.Exceptions.BadRequestException">Illegal path</exception>
5191
5192 </summary>
5193 <param name="source">Base url requested from browser</param>
5194 <param name="destination">Base url on private web server</param>
5195 <example>
5196 // this will return contents from http://192.168.1.128/view/jonas when client requests http://www.gauffin.com/user/view/jonas
5197 _server.Add(new ReverseProxyModule("http://www.gauffin.com/user/", "http://192.168.1.128/");
5198 </example>
5199 </member> 5182 </member>
5200 <member name="M:HttpServer.HttpModules.ReverseProxyModule.CanHandle(System.Uri)"> 5183 <member name="M:HttpServer.HttpModules.FileModule.Contains(System.String,System.Collections.Generic.IEnumerable{System.String})">
5201 <summary> 5184 <summary>
5202 Method that determines if an url should be handled or not by the module 5185 check if source contains any of the chars.
5203 </summary> 5186 </summary>
5204 <param name="uri">Url requested by the client.</param> 5187 <param name="source"></param>
5205 <returns>true if module should handle the url.</returns> 5188 <param name="chars"></param>
5189 <returns></returns>
5206 </member> 5190 </member>
5207 <member name="M:HttpServer.HttpModules.ReverseProxyModule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)"> 5191 <member name="M:HttpServer.HttpModules.FileModule.Process(HttpServer.IHttpRequest,HttpServer.IHttpResponse,HttpServer.Sessions.IHttpSession)">
5208 <summary> 5192 <summary>
5209 Method that process the url 5193 Method that process the Uri.
5210 </summary> 5194 </summary>
5211 <param name="request">Information sent by the browser about the request</param> 5195 <param name="request">Information sent by the browser about the request</param>
5212 <param name="response">Information that is being sent back to the client.</param> 5196 <param name="response">Information that is being sent back to the client.</param>
5213 <param name="session">Session used to </param> 5197 <param name="session">Session used to </param>
5198 <exception cref="T:HttpServer.Exceptions.InternalServerException">Failed to find file extension</exception>
5199 <exception cref="T:HttpServer.Exceptions.ForbiddenException">File type is forbidden.</exception>
5214 </member> 5200 </member>
5215 <member name="T:HttpServer.HttpModules.HttpModuleExceptionEventArgs"> 5201 <member name="M:HttpServer.HttpModules.FileModule.GetFileExtension(System.String)">
5216 <summary> 5202 <summary>
5217 Used to inform http server that 5203 return a file extension from an absolute Uri path (or plain filename)
5218 </summary> 5204 </summary>
5205 <param name="uri"></param>
5206 <returns></returns>
5219 </member> 5207 </member>
5220 <member name="M:HttpServer.HttpModules.HttpModuleExceptionEventArgs.#ctor(System.Exception)"> 5208 <member name="P:HttpServer.HttpModules.FileModule.MimeTypes">
5221 <summary> 5209 <summary>
5222 Eventarguments used when an exception is thrown by a module 5210 List with all mime-type that are allowed.
5223 </summary> 5211 </summary>
5224 <param name="e">the exception</param> 5212 <remarks>All other mime types will result in a Forbidden http status code.</remarks>
5225 </member> 5213 </member>
5226 <member name="P:HttpServer.HttpModules.HttpModuleExceptionEventArgs.Exception"> 5214 <member name="P:HttpServer.HttpModules.FileModule.ForbiddenChars">
5227 <summary> 5215 <summary>
5228 Exception thrown in a module 5216 characters that may not exist in a path.
5229 </summary> 5217 </summary>
5218 <example>
5219 fileMod.ForbiddenChars = new string[]{ "\\", "..", ":" };
5220 </example>
5230 </member> 5221 </member>
5231 <member name="T:HttpServer.Helpers.Implementations.PrototypeImp"> 5222 <member name="T:HttpServer.Helpers.WebHelper">
5232 <summary> 5223 <summary>
5233 PrototypeJS implementation of the javascript functions. 5224 Webhelper provides helpers for common tasks in HTML.
5234 </summary> 5225 </summary>
5235 </member> 5226 </member>
5236 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.AjaxRequest(System.String,System.String[])"> 5227 <member name="F:HttpServer.Helpers.WebHelper.JSImplementation">
5237 <summary> 5228 <summary>
5238 Requests a url through ajax 5229 Used to let the website use different javascript libraries.
5230 Default is <see cref="T:HttpServer.Helpers.Implementations.PrototypeImp"/>
5239 </summary> 5231 </summary>
5240 <param name="url">url to fetch. Url is NOT enclosed in quotes by the implementation. You need to do that yourself.</param>
5241 <param name="options">optional options in format "key, value, key, value", used in JS request object. All keys should end with colon.</param>
5242 <returns>a link tag</returns>
5243 <remarks>onclick attribute is used by this method.</remarks>
5244 <example>
5245 <code>
5246 // plain text
5247 JSHelper.AjaxRequest("'/user/show/1'");
5248
5249 // ajax request using this.href
5250 string link = "&lt;a href=\"/user/call/1\" onclick=\"" + JSHelper.AjaxRequest("this.href") + "/&lt;call user&lt;/a&gt;";
5251 </code>
5252 </example>
5253 </member> 5232 </member>
5254 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.Contains(System.Collections.Generic.IEnumerable{System.String},System.String)"> 5233 <member name="M:HttpServer.Helpers.WebHelper.AjaxRequest(System.String,System.String,System.String[])">
5255 <summary> 5234 <summary>
5256 Determins if a list of strings contains a specific value 5235 Creates a link that invokes through ajax.
5257 </summary> 5236 </summary>
5258 <param name="options">options to check in</param> 5237 <param name="url">url to fetch</param>
5259 <param name="value">value to find</param> 5238 <param name="title">link title</param>
5260 <returns>true if value was found</returns> 5239 <param name="options">
5261 <remarks>case insensitive</remarks> 5240 optional options in format "key, value, key, value".
5241 Javascript options starts with ':'.
5242 </param>
5243 <returns>a link tag</returns>
5244 <example>
5245 WebHelper.AjaxRequest("/users/add/", "Add user", "method:", "post", "onclick", "validate('this');");
5246 </example>
5262 </member> 5247 </member>
5263 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.AjaxUpdater(System.String,System.String,System.String[])"> 5248 <member name="M:HttpServer.Helpers.WebHelper.AjaxUpdater(System.String,System.String,System.String,System.String[])">
5264 <summary> 5249 <summary>
5265 Ajax requests that updates an element with 5250 Builds a link that updates an element with the fetched ajax content.
5266 the fetched content
5267 </summary> 5251 </summary>
5268 <param name="url">URL to fetch. URL is NOT enclosed in quotes by the implementation. You need to do that yourself.</param> 5252 <param name="url">Url to fetch content from</param>
5269 <param name="targetId">element to update</param> 5253 <param name="title">link title</param>
5270 <param name="options">options in format "key, value, key, value". All keys should end with colon.</param> 5254 <param name="targetId">html element to update with the results of the ajax request.</param>
5255 <param name="options">optional options in format "key, value, key, value"</param>
5271 <returns>A link tag.</returns> 5256 <returns>A link tag.</returns>
5272 <example>
5273 <code>
5274 JSHelper.AjaxUpdater("'/user/show/1'", "user", "onsuccess:", "alert('hello');", "asynchronous:", "true");
5275 </code>
5276 </example>
5277 </member> 5257 </member>
5278 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.DialogLink(System.String,System.String,System.String[])"> 5258 <member name="M:HttpServer.Helpers.WebHelper.DialogLink(System.String,System.String,System.String[])">
5279 <summary> 5259 <summary>
5280 A link that pop ups a Dialog (overlay div) 5260 A link that pop ups a Dialog (overlay div)
5281 </summary> 5261 </summary>
5282 <param name="url">URL to contents of dialog</param> 5262 <param name="url">url to contents of dialog</param>
5283 <param name="title">link title</param> 5263 <param name="title">link title</param>
5284 <param name="htmlAttributes">name, value, name, value</param> 5264 <param name="htmlAttributes">name/value of html attributes.</param>
5285 <returns> 5265 <returns>A "a"-tag that popups a dialog when clicked</returns>
5286 A "a"-tag that popups a dialog when clicked
5287 </returns>
5288 <remarks><para>Requires Control.Modal found here: http://livepipe.net/projects/control_modal/</para>
5289 And the following JavaScript (load it in application.js):
5290 <code>
5291 Event.observe(window, 'load',
5292 function() {
5293 document.getElementsByClassName('modal').each(function(link){ new Control.Modal(link); });
5294 }
5295 );
5296 </code>
5297 </remarks>
5298 <example> 5266 <example>
5299 WebHelper.DialogLink("/user/show/1", "show user", "onmouseover", "alert('booh!');"); 5267 WebHelper.DialogLink("/user/show/1", "show user", "onmouseover", "alert('booh!');");
5300 </example> 5268 </example>
5301 </member> 5269 </member>
5302 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.CreateDialog(System.String,System.String,System.String[])"> 5270 <member name="M:HttpServer.Helpers.WebHelper.CreateDialog(System.String,System.String,System.String[])">
5303 <summary> 5271 <summary>
5304 create a modal dialog (usually using DIVs) 5272 Create/Open a dialog box using ajax
5305 </summary> 5273 </summary>
5306 <param name="url">url to fetch</param> 5274 <param name="url"></param>
5307 <param name="title">dialog title</param> 5275 <param name="title"></param>
5308 <param name="options">javascript/html attributes. javascript options ends with colon ':'.</param> 5276 <param name="parameters"></param>
5309 <returns></returns> 5277 <returns></returns>
5310 </member> 5278 </member>
5311 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.CloseDialog"> 5279 <member name="M:HttpServer.Helpers.WebHelper.CloseDialog">
5312 <summary> 5280 <summary>
5313 Close a javascript dialog window/div. 5281 Close a javascript dialog window/div.
5314 </summary> 5282 </summary>
5315 <returns>javascript for closing a dialog.</returns> 5283 <returns>javascript for closing a dialog.</returns>
5316 <see cref="M:HttpServer.Helpers.Implementations.PrototypeImp.DialogLink(System.String,System.String,System.String[])"/> 5284 <see cref="M:HttpServer.Helpers.WebHelper.DialogLink(System.String,System.String,System.String[])"/>
5317 </member> 5285 </member>
5318 <member name="M:HttpServer.Helpers.Implementations.PrototypeImp.AjaxFormOnSubmit(System.String[])"> 5286 <member name="M:HttpServer.Helpers.WebHelper.FormStart(System.String,System.String,System.Boolean)">
5319 <summary> 5287 <summary>
5320 javascript action that should be added to the "onsubmit" event in the form tag. 5288 Create a &lt;form&gt; tag.
5321 </summary> 5289 </summary>
5322 <param name="options">remember to encapsulate strings in ''</param> 5290 <param name="name">name of form</param>
5323 <returns></returns> 5291 <param name="action">action to invoke on submit</param>
5324 <remarks>All javascript option names should end with colon.</remarks> 5292 <param name="isAjax">form should be posted as ajax</param>
5293 <returns>html code</returns>
5325 <example> 5294 <example>
5326 <code> 5295 WebHelper.FormStart("frmLogin", "/user/login", Request.IsAjax);
5327 JSHelper.AjaxRequest("/user/show/1", "onsuccess:", "$('userInfo').update(result);");
5328 </code>
5329 </example> 5296 </example>
5330 </member> 5297 </member>
5331 <member name="T:HttpServer.Authentication.DigestAuthentication"> 5298 <member name="M:HttpServer.Helpers.WebHelper.Link(System.String,System.String,System.String[])">
5332 <summary>
5333 Implements HTTP Digest authentication. It's more secure than Basic auth since password is
5334 encrypted with a "key" from the server.
5335 </summary>
5336 <remarks>
5337 Keep in mind that the password is encrypted with MD5. Use a combination of SSL and digest auth to be secure.
5338 </remarks>
5339 </member>
5340 <member name="M:HttpServer.Authentication.DigestAuthentication.#ctor(HttpServer.Authentication.AuthenticationHandler,HttpServer.Authentication.AuthenticationRequiredHandler)">
5341 <summary>
5342 Initializes a new instance of the <see cref="T:HttpServer.Authentication.DigestAuthentication"/> class.
5343 </summary>
5344 <param name="authenticator">Delegate used to provide information used during authentication.</param>
5345 <param name="authenticationRequiredHandler">Delegate used to determine if authentication is required (may be null).</param>
5346 </member>
5347 <member name="M:HttpServer.Authentication.DigestAuthentication.#ctor(HttpServer.Authentication.AuthenticationHandler)">
5348 <summary>
5349 Initializes a new instance of the <see cref="T:HttpServer.Authentication.DigestAuthentication"/> class.
5350 </summary>
5351 <param name="authenticator">Delegate used to provide information used during authentication.</param>
5352 </member>
5353 <member name="F:HttpServer.Authentication.DigestAuthentication.DisableNonceCheck">
5354 <summary> 5299 <summary>
5355 Used by test classes to be able to use hardcoded values 5300 Create a link tag.
5356 </summary> 5301 </summary>
5302 <param name="url">url to go to</param>
5303 <param name="title">link title (text that is displayed)</param>
5304 <param name="htmlAttributes">html attributes, name, value, name, value</param>
5305 <returns>html code</returns>
5306 <example>
5307 WebHelper.Link("/user/show/1", "Show user", "id", "showUser", "onclick", "return confirm('Are you shure?');");
5308 </example>
5357 </member> 5309 </member>
5358 <member name="M:HttpServer.Authentication.DigestAuthentication.Authenticate(System.String,System.String,System.String,System.Object[])"> 5310 <member name="M:HttpServer.Helpers.WebHelper.BuildLink(System.String,System.String,System.String[])">
5359 <summary> 5311 <summary>
5360 An authentication response have been received from the web browser. 5312 Build a link
5361 Check if it's correct
5362 </summary> 5313 </summary>
5363 <param name="authenticationHeader">Contents from the Authorization header</param> 5314 <param name="url">url to go to.</param>
5364 <param name="realm">Realm that should be authenticated</param> 5315 <param name="title">title of link (displayed text)</param>
5365 <param name="httpVerb">GET/POST/PUT/DELETE etc.</param> 5316 <param name="htmlAttributes">extra html attributes.</param>
5366 <param name="options">First option: true if username/password is correct but not cnonce</param> 5317 <returns>a complete link</returns>
5367 <returns>
5368 Authentication object that is stored for the request. A user class or something like that.
5369 </returns>
5370 <exception cref="T:System.ArgumentException">if authenticationHeader is invalid</exception>
5371 <exception cref="T:System.ArgumentNullException">If any of the paramters is empty or null.</exception>
5372 </member> 5318 </member>
5373 <member name="M:HttpServer.Authentication.DigestAuthentication.Encrypt(System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.String)"> 5319 <member name="M:HttpServer.Helpers.WebHelper.BuildLink(System.String,System.String,System.String[],System.String[])">
5374 <summary> 5320 <summary>
5375 Encrypts parameters into a Digest string 5321 Build a link
5376 </summary> 5322 </summary>
5377 <param name="realm">Realm that the user want to log into.</param> 5323 <param name="url">url to go to.</param>
5378 <param name="userName">User logging in</param> 5324 <param name="title">title of link (displayed text)</param>
5379 <param name="password">Users password.</param> 5325 <param name="htmlAttributes">extra html attributes.</param>
5380 <param name="method">HTTP method.</param> 5326 <returns>a complete link</returns>
5381 <param name="uri">Uri/domain that generated the login prompt.</param> 5327 <param name="options">more options</param>
5382 <param name="qop">Quality of Protection.</param>
5383 <param name="nonce">"Number used ONCE"</param>
5384 <param name="nc">Hexadecimal request counter.</param>
5385 <param name="cnonce">"Client Number used ONCE"</param>
5386 <returns>Digest encrypted string</returns>
5387 </member> 5328 </member>
5388 <member name="M:HttpServer.Authentication.DigestAuthentication.Encrypt(System.String,System.String,System.String,System.String,System.String,System.String)"> 5329 <member name="M:HttpServer.Helpers.WebHelper.Select(System.String,System.Collections.ICollection,HttpServer.Helpers.GetIdTitle,System.Object,System.Boolean)">
5389 <summary> 5330 <summary>
5390 5331 Obsolete
5391 </summary> 5332 </summary>
5392 <param name="ha1">Md5 hex encoded "userName:realm:password", without the quotes.</param> 5333 <param name="name">Obsolete</param>
5393 <param name="ha2">Md5 hex encoded "method:uri", without the quotes</param> 5334 <param name="collection">Obsolete</param>
5394 <param name="qop">Quality of Protection</param> 5335 <param name="getIdTitle">Obsolete</param>
5395 <param name="nonce">"Number used ONCE"</param> 5336 <param name="selectedValue">Obsolete</param>
5396 <param name="nc">Hexadecimal request counter.</param> 5337 <param name="firstEmpty">Obsolete</param>
5397 <param name="cnonce">Client number used once</param> 5338 <returns>Obsolete</returns>
5398 <returns></returns>
5399 </member> 5339 </member>
5400 <member name="M:HttpServer.Authentication.DigestAuthentication.CreateResponse(System.String,System.Object[])"> 5340 <member name="M:HttpServer.Helpers.WebHelper.Select(System.String,System.String,System.Collections.ICollection,HttpServer.Helpers.GetIdTitle,System.Object,System.Boolean)">
5401 <summary> 5341 <summary>
5402 Create a response that can be sent in the WWW-Authenticate header. 5342 Obsolete
5403 </summary> 5343 </summary>
5404 <param name="realm">Realm that the user should authenticate in</param> 5344 <param name="name">Obsolete</param>
5405 <param name="options">First options specifies if true if username/password is correct but not cnonce.</param> 5345 <param name="id">Obsolete</param>
5406 <returns>A correct auth request.</returns> 5346 <param name="collection">Obsolete</param>
5407 <exception cref="T:System.ArgumentNullException">If realm is empty or null.</exception> 5347 <param name="getIdTitle">Obsolete</param>
5348 <param name="selectedValue">Obsolete</param>
5349 <param name="firstEmpty">Obsolete</param>
5350 <returns>Obsolete</returns>
5408 </member> 5351 </member>
5409 <member name="M:HttpServer.Authentication.DigestAuthentication.Decode(System.String,System.Text.Encoding)"> 5352 <member name="M:HttpServer.Helpers.WebHelper.List(System.Collections.Generic.IEnumerable{System.Object},System.String)">
5410 <summary> 5353 <summary>
5411 Decodes authorization header value 5354 Render errors into a UL with class "errors"
5412 </summary> 5355 </summary>
5413 <param name="buffer">header value</param> 5356 <param name="className">class used by UL-tag.</param>
5414 <param name="encoding">Encoding that the buffer is in</param> 5357 <param name="theList">items to list</param>
5415 <returns>All headers and their values if successful; otherwise null</returns> 5358 <returns>an unordered html list.</returns>
5416 <example>
5417 NameValueCollection header = DigestAuthentication.Decode("response=\"6629fae49393a05397450978507c4ef1\",\r\nc=00001", Encoding.ASCII);
5418 </example>
5419 <remarks>Can handle lots of whitespaces and new lines without failing.</remarks>
5420 </member> 5359 </member>
5421 <member name="M:HttpServer.Authentication.DigestAuthentication.GetCurrentNonce"> 5360 <member name="M:HttpServer.Helpers.WebHelper.List(System.Collections.Specialized.NameValueCollection,System.String)">
5422 <summary> 5361 <summary>
5423 Gets the current nonce. 5362 Render errors into a UL with class "errors"
5424 </summary> 5363 </summary>
5425 <returns></returns> 5364 <param name="className">class used by UL-tag.</param>
5365 <param name="theList">items to list</param>
5366 <returns>an unordered html list.</returns>
5426 </member> 5367 </member>
5427 <member name="M:HttpServer.Authentication.DigestAuthentication.GetMD5HashBinHex2(System.String)"> 5368 <member name="M:HttpServer.Helpers.WebHelper.Errors(System.Collections.Specialized.NameValueCollection)">
5428 <summary> 5369 <summary>
5429 Gets the Md5 hash bin hex2. 5370 Render errors into a UL with class "errors"
5430 </summary> 5371 </summary>
5431 <param name="toBeHashed">To be hashed.</param> 5372 <param name="errors"></param>
5432 <returns></returns> 5373 <returns></returns>
5433 </member> 5374 </member>
5434 <member name="M:HttpServer.Authentication.DigestAuthentication.IsValidNonce(System.String)"> 5375 <member name="M:HttpServer.Helpers.WebHelper.GenerateHtmlAttributes(System.Text.StringBuilder,System.String[],System.String[])">
5435 <summary> 5376 <summary>
5436 determines if the nonce is valid or has expired. 5377 Generates a list with html attributes.
5437 </summary> 5378 </summary>
5438 <param name="nonce">nonce value (check wikipedia for info)</param> 5379 <param name="sb">StringBuilder that the options should be added to.</param>
5439 <returns>true if the nonce has not expired.</returns> 5380 <param name="firstOptions">attributes set by user.</param>
5381 <param name="secondOptions">attributes set by any of the helper classes.</param>
5440 </member> 5382 </member>
5441 <member name="P:HttpServer.Authentication.DigestAuthentication.Name"> 5383 <member name="M:HttpServer.Helpers.WebHelper.GenerateHtmlAttributes(System.Text.StringBuilder,System.String[])">
5442 <summary> 5384 <summary>
5443 name used in http request. 5385 Generates a list with html attributes.
5444 </summary> 5386 </summary>
5387 <param name="sb">StringBuilder that the options should be added to.</param>
5388 <param name="options"></param>
5445 </member> 5389 </member>
5446 <member name="P:HttpServer.Authentication.DigestAuthentication.TokenIsHA1"> 5390 <member name="T:HttpServer.Helpers.GetIdTitle">
5447 <summary> 5391 <summary>
5448 Gets or sets whether the token supplied in <see cref="T:HttpServer.Authentication.AuthenticationHandler"/> is a 5392 Delegate used by <see cref="M:HttpServer.Helpers.FormHelper.Select(System.String,System.Collections.IEnumerable,HttpServer.Helpers.GetIdTitle,System.Object,System.Boolean)"/> to populate select options.
5449 HA1 generated string.
5450 </summary> 5393 </summary>
5394 <param name="obj">current object (for instance a User).</param>
5395 <param name="id">Text that should be displayed in the value part of a &lt;optiongt;-tag.</param>
5396 <param name="title">Text shown in the select list.</param>
5397 <example>
5398 // Class that is going to be used in a SELECT-tag.
5399 public class User
5400 {
5401 private readonly string _realName;
5402 private readonly int _id;
5403 public User(int id, string realName)
5404 {
5405 _id = id;
5406 _realName = realName;
5407 }
5408 public string RealName
5409 {
5410 get { return _realName; }
5411 }
5412
5413 public int Id
5414 {
5415 get { return _id; }
5416 }
5417 }
5418
5419 // Using an inline delegate to generate the select list
5420 public void UserInlineDelegate()
5421 {
5422 List&lt;User&gt; items = new List&lt;User&gt;();
5423 items.Add(new User(1, "adam"));
5424 items.Add(new User(2, "bertial"));
5425 items.Add(new User(3, "david"));
5426 string htmlSelect = Select("users", "users", items, delegate(object o, out object id, out object value)
5427 {
5428 User user = (User)o;
5429 id = user.Id;
5430 value = user.RealName;
5431 }, 2, true);
5432 }
5433
5434 // Using an method as delegate to generate the select list.
5435 public void UseExternalDelegate()
5436 {
5437 List&lt;User&gt; items = new List&lt;User&gt;();
5438 items.Add(new User(1, "adam"));
5439 items.Add(new User(2, "bertial"));
5440 items.Add(new User(3, "david"));
5441 string htmlSelect = Select("users", "users", items, UserOptions, 1, true);
5442 }
5443
5444 // delegate returning id and title
5445 public static void UserOptions(object o, out object id, out object title)
5446 {
5447 User user = (User)o;
5448 id = user.Id;
5449 value = user.RealName;
5450 } /// </example>
5451 </member> 5451 </member>
5452 </members> 5452 </members>
5453</doc> 5453</doc>
diff --git a/bin/Mono.Addins.CecilReflector.dll b/bin/Mono.Addins.CecilReflector.dll
index a1a6382..9ca4631 100755
--- a/bin/Mono.Addins.CecilReflector.dll
+++ b/bin/Mono.Addins.CecilReflector.dll
Binary files differ
diff --git a/bin/Mono.Addins.Setup.dll b/bin/Mono.Addins.Setup.dll
index 8aa6d5f..75773aa 100755
--- a/bin/Mono.Addins.Setup.dll
+++ b/bin/Mono.Addins.Setup.dll
Binary files differ
diff --git a/bin/Mono.Addins.dll b/bin/Mono.Addins.dll
index ea330fd..326ed1d 100755
--- a/bin/Mono.Addins.dll
+++ b/bin/Mono.Addins.dll
Binary files differ
diff --git a/bin/OpenMetaverse.dll.config b/bin/OpenMetaverse.dll.config
index b67da5f..f5423b2 100644
--- a/bin/OpenMetaverse.dll.config
+++ b/bin/OpenMetaverse.dll.config
@@ -1,5 +1,5 @@
1<configuration> 1<configuration>
2 <dllmap os="osx" dll="openjpeg-dotnet.dll" target="lib64/libopenjpeg-dotnet-2.1.5.0-dotnet-1.dylib" /> 2 <dllmap os="osx" dll="openjpeg-dotnet.dll" target="lib64/libopenjpeg-dotnet.dylib" />
3 <dllmap os="!windows,osx" cpu="x86-64,ia64" dll="openjpeg-dotnet-x86_64.dll" target="lib64/libopenjpeg-dotnet-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" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet" /> 4 <dllmap os="!windows,osx" cpu="x86" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet" />
5</configuration> 5</configuration>
diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config
index e3107ab..8a891f4 100755
--- a/bin/OpenSim.exe.config
+++ b/bin/OpenSim.exe.config
@@ -32,9 +32,15 @@
32 <appender-ref ref="LogFileAppender" /> 32 <appender-ref ref="LogFileAppender" />
33 </root> 33 </root>
34 34
35 <!-- Independently control logging level for XEngine -->
35 <logger name="OpenSim.Region.ScriptEngine.XEngine"> 36 <logger name="OpenSim.Region.ScriptEngine.XEngine">
36 <level value="INFO"/> 37 <level value="INFO"/>
37 </logger> 38 </logger>
38 39
40 <!-- Independently control logging level for per region module loading -->
41 <logger name="OpenSim.ApplicationPlugins.RegionModulesController.RegionModulesControllerPlugin">
42 <level value="INFO"/>
43 </logger>
44
39 </log4net> 45 </log4net>
40</configuration> 46</configuration>
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 6757081..7e7b231 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -206,12 +206,13 @@
206 ;; Choose one of the physics engines below 206 ;; Choose one of the physics engines below
207 ;# {physics} {} {Select physics engine} {OpenDynamicsEngine BulletSim basicphysics POS} OpenDynamicsEngine 207 ;# {physics} {} {Select physics engine} {OpenDynamicsEngine BulletSim basicphysics POS} OpenDynamicsEngine
208 ;; OpenDynamicsEngine is by some distance the most developed physics engine 208 ;; OpenDynamicsEngine is by some distance the most developed physics engine
209 ;; BulletSim is incomplete and experimental but in active development 209 ;; BulletSim is incomplete and experimental but in active development. BulletSimN is a purely C# version of BulletSim.
210 ;; basicphysics effectively does not model physics at all, making all 210 ;; basicphysics effectively does not model physics at all, making all
211 ;; objects phantom 211 ;; objects phantom.
212 ;; Default is OpenDynamicsEngine 212 ;; Default is OpenDynamicsEngine
213 ; physics = OpenDynamicsEngine 213 ; physics = OpenDynamicsEngine
214 ; physics = BulletSim 214 ; physics = BulletSim
215 ; physics = BulletSimN
215 ; physics = basicphysics 216 ; physics = basicphysics
216 ; physics = POS 217 ; physics = POS
217 218
@@ -264,9 +265,10 @@
264 ; DefaultScriptEngine = "XEngine" 265 ; DefaultScriptEngine = "XEngine"
265 266
266 ;# {GenerateMaptiles} {} {Generate map tiles?} {true false} true 267 ;# {GenerateMaptiles} {} {Generate map tiles?} {true false} true
267 ;; Map tile options. You can choose to generate no map tiles at all, 268 ;; Map tile options. You can choose to generate normal maptiles or nominate an uploaded texture to
268 ;; generate normal maptiles, or nominate an uploaded texture to 269 ;; be the map tile using the MaptileStaticUUID parameter in this section or for individual regions in
269 ;; be the map tile 270 ;; the regions config file(s). If you do not want to upload map tiles at all, then you will need
271 ;; to disable the MapImageServiceModule entirely.
270 ; GenerateMaptiles = true 272 ; GenerateMaptiles = true
271 273
272 ;# {MaptileRefresh} {GenerateMaptiles} {Maptile refresh period?} {} 0 274 ;# {MaptileRefresh} {GenerateMaptiles} {Maptile refresh period?} {} 0
@@ -744,13 +746,6 @@
744 ;; The trade-off may be increased memory usage by the script engine. 746 ;; The trade-off may be increased memory usage by the script engine.
745 ; ThreadStackSize = 262144 747 ; ThreadStackSize = 262144
746 748
747 ;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true
748 ;; Controls whether previously compiled scripts DLLs are deleted on sim restart. If you set this to false
749 ;; then startup will be considerably faster since scripts won't need to be recompiled. However, then it becomes your responsibility to delete the
750 ;; compiled scripts if you're recompiling OpenSim from source code and internal interfaces used
751 ;; by scripts have changed.
752 ; DeleteScriptsOnStartup = true
753
754 ;; Set this to true (the default) to load each script into a separate 749 ;; Set this to true (the default) to load each script into a separate
755 ;; AppDomain. 750 ;; AppDomain.
756 ;; 751 ;;
@@ -763,6 +758,23 @@
763 ;; Some Windows users have also reported script loading problems when AppDomainLoading = false 758 ;; Some Windows users have also reported script loading problems when AppDomainLoading = false
764 ; AppDomainLoading = true 759 ; AppDomainLoading = true
765 760
761 ;; Controls whether scripts are stopped by aborting their threads externally (abort) or by co-operative checks from the compiled script (co-op)
762 ;; co-op will be more stable but this option is currently experimental.
763 ;; If moving from co-op to abort, existing script DLLs will need to be recompiled.
764 ;; This currently can only be done manually, either by setting DeleteScriptsOnStartup = true for one run
765 ;; or by deleting the script DLL* files in bin/ScriptEngines/<region-id>/
766 ;; One can move from co-op back to abort without recompilation, but reverting back to co-op again will need script recompile
767 ;; Current valid values are "abort" and "co-op"
768 ; ScriptStopStrategy = abort
769
770
771 ;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true
772 ;; Controls whether previously compiled scripts DLLs are deleted on sim restart. If you set this to false
773 ;; then startup will be considerably faster since scripts won't need to be recompiled. However, then it becomes your responsibility to delete the
774 ;; compiled scripts if you're recompiling OpenSim from source code and internal interfaces used
775 ;; by scripts have changed.
776 ; DeleteScriptsOnStartup = true
777
766 ;# {DefaultCompileLanguage} {Enabled:true} {Default script language?} {lsl vb cs} lsl 778 ;# {DefaultCompileLanguage} {Enabled:true} {Default script language?} {lsl vb cs} lsl
767 ;; Default language for scripts 779 ;; Default language for scripts
768 ; DefaultCompileLanguage = "lsl" 780 ; DefaultCompileLanguage = "lsl"
@@ -786,8 +798,9 @@
786 ;; Allow the use of os* functions (some are dangerous) 798 ;; Allow the use of os* functions (some are dangerous)
787 ; AllowOSFunctions = false 799 ; AllowOSFunctions = false
788 800
789 ;# {AllowLightShareFunctions} {Enabled:true [LightShare]enable_windlight:true} {Allow LightShare functions?} {true false} true 801 ;# {AllowLightShareFunctions} {Enabled:false [LightShare]enable_windlight:true} {Allow LightShare functions?} {true false} false
790 ; Allow the user of LightShare functions 802 ; Allow the use of LightShare functions.
803 ; The setting enable_windlight = true must also be enabled in the [LightShare] section.
791 ; AllowLightShareFunctions = false 804 ; AllowLightShareFunctions = false
792 805
793 ;# {OSFunctionThreatLevel} {Enabled:true AllowOSFunctions:true} {OSFunction threat level? (DANGEROUS!)} {None VeryLow Low Moderate High VeryHigh Severe} VeryLow 806 ;# {OSFunctionThreatLevel} {Enabled:true AllowOSFunctions:true} {OSFunction threat level? (DANGEROUS!)} {None VeryLow Low Moderate High VeryHigh Severe} VeryLow
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 54f252e..6409cdb 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -1,7 +1,6 @@
1; This file contains defaults for various settings in OpenSimulator. These can be overriden 1; This file contains defaults for various settings in OpenSimulator. These can be overriden
2; by changing the same setting in OpenSim.ini (once OpenSim.ini.example has been copied to OpenSim.ini). 2; by changing the same setting in OpenSim.ini (once OpenSim.ini.example has been copied to OpenSim.ini).
3 3
4
5[Startup] 4[Startup]
6 ; Console prompt 5 ; Console prompt
7 ; Certain special characters can be used to customize the prompt 6 ; Certain special characters can be used to customize the prompt
@@ -217,10 +216,10 @@
217 ; to false if you have compatibility problems. 216 ; to false if you have compatibility problems.
218 ;CacheSculptMaps = true 217 ;CacheSculptMaps = true
219 218
220 ; Choose one of the physics engines below 219 ; Choose one of the physics engines below.
221 ; OpenDynamicsEngine is by some distance the most developed physics engine 220 ; OpenDynamicsEngine is by some distance the most developed physics engine.
222 ; basicphysics effectively does not model physics at all, making all objects phantom 221 ; BulletSim is a high performance, up-and-coming physics engine.
223 222 ; basicphysics effectively does not model physics at all, making all objects phantom.
224 physics = OpenDynamicsEngine 223 physics = OpenDynamicsEngine
225 ;physics = basicphysics 224 ;physics = basicphysics
226 ;physics = POS 225 ;physics = POS
@@ -364,6 +363,12 @@
364 ; alert_uri = "http://myappserver.net/my_handler/" 363 ; alert_uri = "http://myappserver.net/my_handler/"
365 364
366 365
366[EstateManagement]
367 ; If false, then block any region restart requests from the client even if they are otherwise valid.
368 ; Default is true
369 AllowRegionRestartFromClient = true
370
371
367[SMTP] 372[SMTP]
368 enabled = false 373 enabled = false
369 374
@@ -898,17 +903,29 @@
898 903
899[BulletSim] 904[BulletSim]
900 ; World parameters 905 ; World parameters
901 DefaultFriction = 0.50 906
902 DefaultDensity = 10.000006836 907 ; There are two bullet physics libraries, bulletunmanaged is the default and is a native c++ dll
903 DefaultRestitution = 0.0 908 ; bulletxna is a managed C# dll. They have comparible functionality.. the c++ is much faster.
909
910 BulletEngine = "bulletunmanaged"
911 ; BulletEngine = "bulletxna"
912
913 ; Terrain Implementation {1|0} 0 for HeightField, 1 for Mesh terrain. If you're using the bulletxna engine,
914 ; you will want to switch to the heightfield option
915 TerrainImplementation = 1
916 ; TerrainImplementation = 0
917
904 Gravity = -9.80665 918 Gravity = -9.80665
905 919
906 TerrainFriction = 0.50 920 TerrainFriction = 0.30
907 TerrainHitFriction = 0.8 921 TerrainHitFraction = 0.8
908 TerrainRestitution = 0 922 TerrainRestitution = 0
923 TerrainCollisionMargin = 0.04
924
909 AvatarFriction = 0.2 925 AvatarFriction = 0.2
926 AvatarStandingFriction = 0.95
910 AvatarRestitution = 0.0 927 AvatarRestitution = 0.0
911 AvatarDensity = 60.0 928 AvatarDensity = 3.5
912 AvatarCapsuleWidth = 0.6 929 AvatarCapsuleWidth = 0.6
913 AvatarCapsuleDepth = 0.45 930 AvatarCapsuleDepth = 0.45
914 AvatarCapsuleHeight = 1.5 931 AvatarCapsuleHeight = 1.5
@@ -916,30 +933,10 @@
916 933
917 MaxObjectMass = 10000.01 934 MaxObjectMass = 10000.01
918 935
919 ; Dynamic parameters 936 CollisionMargin = 0.04
920 LinearDamping = 0.0
921 AngularDamping = 0.0
922 DeactivationTime = 0.2
923 LinearSleepingThreshold = 0.8
924 AngularSleepingThreshold = 1.0
925 CcdMotionThreshold = 0.0
926 CcdSweptSphereRadius = 0.0
927 ContactProcessingThreshold = 0.1
928 ; If setting a pool size, also disable dynamic allocation (default pool size is 4096 with dynamic alloc)
929 MaxPersistantManifoldPoolSize = 0
930 ShouldDisableContactPoolDynamicAllocation = False
931 ShouldForceUpdateAllAabbs = False
932 ShouldRandomizeSolverOrder = True
933 ShouldSplitSimulationIslands = True
934 ShouldEnableFrictionCaching = False
935 NumberOfSolverIterations = 0
936
937 ; Linkset constraint parameters
938 LinkConstraintUseFrameOffset = False
939 LinkConstraintEnableTransMotor = True
940 LinkConstraintTransMotorMaxVel = 5.0
941 LinkConstraintTransMotorMaxForce = 0.1
942 937
938 ; Linkset implmentation
939 LinkImplementation = 1 ; 0=constraint, 1=compound
943 940
944 ; Whether to mesh sculpties 941 ; Whether to mesh sculpties
945 MeshSculptedPrim = true 942 MeshSculptedPrim = true
@@ -947,14 +944,6 @@
947 ; If 'true', force simple prims (box and sphere) to be meshed 944 ; If 'true', force simple prims (box and sphere) to be meshed
948 ForceSimplePrimMeshing = false 945 ForceSimplePrimMeshing = false
949 946
950 ; level of detail for physical meshes. 32,16,8 or 4 with 32 being full detail
951 MeshLevelOfDetail = 8
952 ; if mesh size is > threshold meters, we need to add more detail because people will notice
953 MeshLevelOfDetailMegaPrimThreshold = 10
954 MeshLevelOfDetailMegaPrim = 16
955 ; number^2 non-physical level of detail of the sculpt texture. 32x32 - 1024 verticies
956 SculptLevelOfDetail = 32
957
958 ; Bullet step parameters 947 ; Bullet step parameters
959 MaxSubSteps = 10 948 MaxSubSteps = 10
960 FixedTimeStep = .01667 949 FixedTimeStep = .01667
@@ -966,6 +955,7 @@
966 PhysicsLoggingEnabled = False 955 PhysicsLoggingEnabled = False
967 PhysicsLoggingDir = "." 956 PhysicsLoggingDir = "."
968 VehicleLoggingEnabled = False 957 VehicleLoggingEnabled = False
958
969 959
970[RemoteAdmin] 960[RemoteAdmin]
971 enabled = false 961 enabled = false
@@ -1116,6 +1106,17 @@
1116 1106
1117 ;exclude_list=User 1,User 2,User 3 1107 ;exclude_list=User 1,User 2,User 3
1118 1108
1109 ;;Shows modal alertbox for entering agent on IRC enabled regions
1110 ;;
1111 ;; Enable Alert, default = false
1112 ;alert_show = false
1113 ;;
1114 ;; Show IRC serverinfo, default = true
1115 ;alert_show_serverinfo = true
1116 ;;
1117 ;alert_msg_pre = "This region is linked to Irc."
1118 ;alert_msg_post = "Everything you say in public chat can be listened."
1119
1119 1120
1120; The following settings control the progression of daytime 1121; The following settings control the progression of daytime
1121; in the Sim. The defaults are the same as the commented out settings 1122; in the Sim. The defaults are the same as the commented out settings
@@ -1297,6 +1298,20 @@
1297 ; script assemblies 1298 ; script assemblies
1298 AppDomainLoading = true 1299 AppDomainLoading = true
1299 1300
1301 ; Controls whether previously compiled scripts DLLs are deleted on sim restart. If you set this to false
1302 ; then startup will be considerably faster since scripts won't need to be recompiled. However, then it becomes your responsibility to delete the
1303 ; compiled scripts if you're recompiling OpenSim from source code and internal interfaces used
1304 ; by scripts have changed.
1305 ; DeleteScriptsOnStartup = false
1306
1307 ; Controls whether scripts are stopped by aborting their threads externally (abort) or by co-operative checks from the compiled script (co-op)
1308 ; co-op will be more stable but this option is currently experimental.
1309 ; If moving from co-op to abort, existing script DLLs will need to be recompiled.
1310 ; This currently can only be done manually, either by setting DeleteScriptsOnStartup = true for one run
1311 ; or by deleting the script DLL* files in bin/ScriptEngines/<region-id>/
1312 ; One can move from co-op back to abort without recompilation, but reverting back to co-op again will need script recompile
1313 ScriptStopStrategy = abort
1314
1300 ; Rate to poll for asynchronous command replies (ms) 1315 ; Rate to poll for asynchronous command replies (ms)
1301 ; currently unused 1316 ; currently unused
1302 ;AsyncLLCommandLoopms = 50 1317 ;AsyncLLCommandLoopms = 50
@@ -1367,6 +1382,10 @@
1367 ; If a script overruns it's event limit, kill the script? 1382 ; If a script overruns it's event limit, kill the script?
1368 KillTimedOutScripts = false 1383 KillTimedOutScripts = false
1369 1384
1385 ; Amount of time in milliseconds we will wait for an event to completely normally when a script stop is requested
1386 ; before aborting the thread (such as when an object containing scripts is taken into inventory).
1387 WaitForEventCompletionOnScriptStop = 1000;
1388
1370 ; Sets the multiplier for the scripting delays 1389 ; Sets the multiplier for the scripting delays
1371 ScriptDelayFactor = 1.0 1390 ScriptDelayFactor = 1.0
1372 1391
@@ -1394,12 +1413,6 @@
1394 ;; Path to script assemblies 1413 ;; Path to script assemblies
1395 ; ScriptEnginesPath = "ScriptEngines" 1414 ; ScriptEnginesPath = "ScriptEngines"
1396 1415
1397 ; Controls whether previously compiled scripts DLLs are deleted on sim restart. If you set this to false
1398 ; then startup will be considerably faster since scripts won't need to be recompiled. However, then it becomes your responsibility to delete the
1399 ; compiled scripts if you're recompiling OpenSim from source code and internal interfaces used
1400 ; by scripts have changed.
1401 ; DeleteScriptsOnStartup = false
1402
1403 1416
1404[Concierge] 1417[Concierge]
1405 ; Enable concierge module 1418 ; Enable concierge module
@@ -1582,8 +1595,7 @@
1582 1595
1583 ; If true, then the basic packet objects used to receive data are also recycled, not just the LLUDP packets. 1596 ; If true, then the basic packet objects used to receive data are also recycled, not just the LLUDP packets.
1584 ; This reduces data churn 1597 ; This reduces data churn
1585 ; This setting is currently experimental and defaults to false. 1598 RecycleBaseUDPPackets = true
1586 RecycleBaseUDPPackets = false;
1587 1599
1588 1600
1589[InterestManagement] 1601[InterestManagement]
diff --git a/bin/Regions/Regions.ini.example b/bin/Regions/Regions.ini.example
index 54a841d..ab3a62a 100644
--- a/bin/Regions/Regions.ini.example
+++ b/bin/Regions/Regions.ini.example
@@ -45,3 +45,8 @@ ExternalHostName = "SYSTEMIP"
45; * 45; *
46 46
47; RegionType = "Mainland" 47; RegionType = "Mainland"
48
49; *
50; * UUID of texture to use as a maptile for this region.
51; * Only set if you have disabled dynamic generation of the map tile from the region contents.
52; MaptileStaticUUID = "00000000-0000-0000-0000-000000000000"
diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example
index 4ecc6b0..c7d4b7f 100644
--- a/bin/Robust.HG.ini.example
+++ b/bin/Robust.HG.ini.example
@@ -22,6 +22,18 @@
22; * 22; *
23[Startup] 23[Startup]
24 24
25; Plugin Registry Location
26; Set path to directory for plugin registry. Information
27; about the registered repositories and installed plugins
28; will be stored here
29; The Robust.exe process must hvae R/W access to the location
30RegistryLocation = "."
31
32; Modular configurations
33; Set path to directory for modular ini files...
34; The Robust.exe process must hvae R/W access to the location
35ConfigDirectory = "/home/opensim/etc/Configs"
36
25[ServiceList] 37[ServiceList]
26 38
27AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector" 39AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
@@ -53,7 +65,6 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
53;; Additions for other add-on modules. For example: 65;; Additions for other add-on modules. For example:
54;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector" 66;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector"
55 67
56
57; * This is common for all services, it's the network setup for the entire 68; * This is common for all services, it's the network setup for the entire
58; * server instance, if none is specified above 69; * server instance, if none is specified above
59; * 70; *
diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example
index 7503c5e..bc5cbcc 100644
--- a/bin/Robust.ini.example
+++ b/bin/Robust.ini.example
@@ -14,6 +14,19 @@
14; * 14; *
15[Startup] 15[Startup]
16 16
17; Plugin Registry Location
18; Set path to directory for plugin registry. Information
19; about the registered repositories and installed plugins
20; will be stored here
21; The Robust.exe process must hvae R/W access to the location
22RegistryLocation = "."
23
24
25; Modular configurations
26; Set path to directory for modular ini files...
27; The Robust.exe process must hvae R/W access to the location
28ConfigDirectory = "/home/opensim/etc/Configs"
29
17[ServiceList] 30[ServiceList]
18AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector" 31AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
19InventoryInConnector = "8003/OpenSim.Server.Handlers.dll:XInventoryInConnector" 32InventoryInConnector = "8003/OpenSim.Server.Handlers.dll:XInventoryInConnector"
diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example
index 79f7ed6..e53fcca 100644
--- a/bin/config-include/GridCommon.ini.example
+++ b/bin/config-include/GridCommon.ini.example
@@ -137,6 +137,11 @@
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 ;; Send visual reminder to local users that their inventories are unavailable while they are traveling
141 ;; and available when they return. True by default.
142 ;RestrictInventoryAccessAbroad = True
143
144
140[HGAssetService] 145[HGAssetService]
141 ; 146 ;
142 ; === HG ONLY === 147 ; === HG ONLY ===
diff --git a/bin/data/LICENSE-README-IMPORTANT.txt b/bin/data/LICENSE-README-IMPORTANT.txt
index 86e401f..a1ac20c 100644
--- a/bin/data/LICENSE-README-IMPORTANT.txt
+++ b/bin/data/LICENSE-README-IMPORTANT.txt
@@ -2,4 +2,4 @@ Not all of the files in this directory are licensed under the BSD license. Some
2 2
3These files are: 3These files are:
4 4
5- avataranimations.xml (Derivative work of viewerart.ini, Creative Commons Attribution+Share-Alike v2.5 License) \ No newline at end of file 5- avataranimations.xml (Derivative work of viewerart.ini, Creative Commons Attribution+Share-Alike v2.5 License)
diff --git a/bin/data/sim.css b/bin/data/sim.css
new file mode 100644
index 0000000..e584a1a
--- /dev/null
+++ b/bin/data/sim.css
@@ -0,0 +1,85 @@
1body {
2 font-family: Veranda,Arial,Helvetica,sans-serif;
3 font-size: 12px;
4 background: #4A5F6D;
5 color: #EEEAD6;
6 padding: 0px;
7 margin: 0px;
8}
9.footer {
10 font-family: Veranda,Arial,Helvetica,sans-serif;
11 font-size: 10px;
12}
13td {
14 font-family: Veranda,Arial,Helvetica,sans-serif;
15 font-size: 12px;
16 padding: 4px;
17 margin: 4px;
18}
19blockquote {
20 font-family: Veranda,Arial,Helvetica,sans-serif;
21 font-style: italic;
22 font-size: 12px;
23}
24pre {
25 padding: 5px;
26 background-color: #8080B0;
27 color: #000000;
28 margin-left: 20px;
29 font-size: 11px;
30}
31:link {
32 color: #ffffff;
33}
34:visited {
35 color: #d0d0d0;
36}
37.SimSectionHeader {
38 font-size: 120%;
39}
40div.SimSectionContainer {
41 padding: 10px 0px 0px 20px;
42}
43/* SimStats ===================================== */
44#SimSimStats div {
45 margin-left: 20px;
46 background: #3A4F5D;
47}
48#SimSimStats table td {
49 text-align: right;
50 padding: 0px 0px 0px 5px;
51 margin: 0px 0px 0px 0px;
52}
53/* Region Stats ===================================== */
54#SimRegionStats div {
55 margin-left: 20px;
56 background: #3A4F5D;
57}
58#SimRegionStats table {
59 border: 1px;
60 border-style: solid;
61}
62#SimRegionStats table td {
63 text-align: right;
64 padding: 0px 0px 0px 5px;
65 margin: 0px 0px 0px 0px;
66}
67/* Session Stats ===================================== */
68#SimSessionStats div {
69 margin-left: 20px;
70 background: #3A4F5D;
71}
72#SimSessionStats table td {
73 text-align: right;
74 padding: 0px 0px 0px 5px;
75 margin: 0px 0px 0px 0px;
76}
77/* LogFile ===================================== */
78#SimLogFile div {
79 margin-left: 20px;
80}
81#SimLogFile table td {
82 text-align: right;
83 padding: 0px 0px 0px 5px;
84 margin: 0px 0px 0px 0px;
85}
diff --git a/bin/data/sim.html b/bin/data/sim.html
new file mode 100644
index 0000000..82d4789
--- /dev/null
+++ b/bin/data/sim.html
@@ -0,0 +1,291 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml">
4<head>
5<title>Simulator statistics</title>
6<link rel="stylesheet" href="sim.css" type="text/css"/>
7<!-- <script type="text/javascript" src="jquery.js"></script> -->
8<!-- <script type="text/javascript" src="https://code.jquery.com/jquery-1.9.0.min.js"></script> -->
9<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
10<!-- <script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/libs/jQuery/jquery-1.9.0.min.js"></script> -->
11<noscript>
12<p color="red">
13Your browser does not support Javascript. This won't work for you.
14</p>
15</noscript>
16<script type="text/javascript">
17$(document).ready(function() {
18 // Major divisions in the content accordioning
19 $('.SimSection').show('slow');
20 $('.SimSectionHeader').click(function() {
21 $(this).next().slideToggle('slow');
22 return false;
23 });
24
25 // Start the timed functions
26 TimerDataStuff();
27});
28
29// One of the sections is viewer statistics. Poll for the data.
30var statTimerHandle;
31var graphFPS;
32var lastFPS = 10;
33var xxThru = 0;
34function TimerDataStuff() {
35 statTimerHandle = setInterval('TimerStatDisplay()', 5000);
36}
37
38// called by timer to fetch and display statistic information
39var doingStatDisplay = false;
40function TimerStatDisplay() {
41 if (doingStatDisplay) return;
42 doingStatDisplay = true;
43 if ($('#SimSimStats').is(':visible')) {
44 DisplaySimStats();
45 }
46 if ($('#SimRegionStats').is(':visible')) {
47 DisplayPerRegionStats();
48 }
49 if ($('#SimSessionStats').is(':visible')) {
50 DisplaySessionStats();
51 }
52 if ($('#SimLogFile').is(':visible')) {
53 DisplayLogFile();
54 }
55 doingStatDisplay = false;
56}
57
58var simName = "127.0.0.1";
59var simPort = "9000";
60function DisplaySimStats() {
61 var statURL = "http://" + simName + ":" + simPort + "/SStats/?json=1";
62 $.ajax({
63 type: "GET",
64 url: statURL,
65 dataType: 'json',
66 timeout: 1000,
67 success: function(data, status) {
68 if (status == 'success') {
69 DisplaySimStatDetails(data);
70 }
71 },
72 error: function(xmlHTTPRequest, errorType) {
73 // DebugLog('Failed fetch');
74 }
75 });
76}
77
78function DisplayPerRegionStats() {
79 var statURL = "http://" + simName + ":" + simPort + "/SStats/simstatsajax.html?json=1";
80 $.ajax({
81 type: "GET",
82 url: statURL,
83 dataType: 'json',
84 timeout: 1000,
85 success: function(data, status) {
86 if (status == 'success') {
87 DisplayRegionStatDetails(data);
88 }
89 },
90 error: function(xmlHTTPRequest, errorType) {
91 // DebugLog('Failed fetch');
92 }
93 });
94};
95
96function DisplayLogFile() {
97 var statURL = "http://" + simName + ":" + simPort + "/SStats/activelogajax.html?json=1";
98 $.ajax({
99 type: "GET",
100 url: statURL,
101 dataType: 'json',
102 timeout: 1000,
103 success: function(data, status) {
104 if (status == 'success') {
105 DisplayLogFileDetails(data);
106 }
107 },
108 error: function(xmlHTTPRequest, errorType) {
109 // DebugLog('Failed fetch');
110 }
111 });
112};
113
114function DisplaySessionStats() {
115 var statURL = "http://" + simName + ":" + simPort + "/SStats/activeconnectionsajax.html?json=1";
116 $.ajax({
117 type: "GET",
118 url: statURL,
119 dataType: 'json',
120 timeout: 1000,
121 success: function(data, status) {
122 if (status == 'success') {
123 DisplaySessionStatsDetails(data);
124 }
125 },
126 error: function(xmlHTTPRequest, errorType) {
127 // DebugLog('Failed fetch');
128 }
129 });
130};
131
132function DisplaySimStatDetails(data) {
133 var simInfo = new StringBuffer();
134 simInfo.append('<table id="RegionStatsTable">');
135 simInfo.append('<tr>');
136 simInfo.append('<th>Total Users</th>');
137 simInfo.append('<th>Total Sessions</th>');
138 simInfo.append('<th>Avg client FPS</th>');
139 simInfo.append('<th>Avg client Mem</th>');
140 simInfo.append('<th>Avg ping time</th>');
141 simInfo.append('<th>KB out</th>');
142 simInfo.append('<th>KB in</th>');
143 simInfo.append('</tr>');
144 simInfo.append('<tr>');
145 simInfo.append('<td>' + data.totalUsers + '</td>');
146 simInfo.append('<td>' + data.totalSessions + '</td>');
147 simInfo.append('<td>' + data.averageClientFPS + '</td>');
148 simInfo.append('<td>' + data.averageClientMem + '</td>');
149 simInfo.append('<td>' + data.averagePingTime + '</td>');
150 simInfo.append('<td>' + data.totalKBOut + '</td>');
151 simInfo.append('<td>' + data.totalKBIn + '</td>');
152 simInfo.append('</tr>');
153 simInfo.append('</table>');
154 $('#SimSimStats').empty();
155 $('#SimSimStats').append(simInfo.toString());
156}
157
158function DisplayRegionStatDetails(data) {
159 var regionInfo = new StringBuffer();
160 regionInfo.append('<table id="RegionStatsTable">');
161 regionInfo.append('<tr>');
162 regionInfo.append('<th>Region</th>');
163 regionInfo.append('<th>Agents</th>');
164 regionInfo.append('<th>Child</th>');
165 regionInfo.append('<th>FPS</th>');
166 regionInfo.append('<th>Frame Time</th>');
167 regionInfo.append('<th>Phys Time</th>');
168 regionInfo.append('<th>Prims</th>');
169 regionInfo.append('</tr>');
170 for (region in data) {
171 regionInfo.append('<tr>');
172 regionInfo.append('<td>' + data[region].region + '</td>');
173 regionInfo.append('<td>' + data[region].rootAgents + '</td>');
174 regionInfo.append('<td>' + data[region].childAgents + '</td>');
175 regionInfo.append('<td>' + data[region].simFPS + '</td>');
176 regionInfo.append('<td>' + data[region].totalFrameTime + '</td>');
177 regionInfo.append('<td>' + data[region].physicsFrameTime + '</td>');
178 regionInfo.append('<td>' + data[region].totalPrims + '</td>');
179 regionInfo.append('</tr>');
180 }
181 regionInfo.append('</table>');
182 $('#SimRegionStats').empty();
183 $('#SimRegionStats').append(regionInfo.toString());
184}
185
186function DisplayLogFileDetails(data) {
187 var logInfo = new StringBuffer();
188 var logPattern = /^(.+),\d\d\d .* \[(.+)\]: (.+)$/;
189 for (logLine in data['logLines']) {
190 logInfo.append('<div>');
191 var logPieces = logPattern.exec(data['logLines'][logLine]);
192 if (logPieces) {
193 logInfo.append(logPieces[1] + ' [' + logPieces[2]
194 + '] ' + logPieces[3]);
195 }
196 else {
197 logInfo.append(data['logLines'][logLine]);
198 }
199
200 logInfo.append('</div>');
201 }
202 $('#SimLogFile').empty();
203 $('#SimLogFile').append(logInfo.toString());
204}
205
206function DisplaySessionStatsDetails(data) {
207 var userInfo = new StringBuffer();
208 userInfo.append('<table>');
209 userInfo.append('<tr>');
210 userInfo.append('<th>region</th>');
211 userInfo.append('<th>user</th>');
212 userInfo.append('<th></th>');
213 userInfo.append('<th>position</th>');
214 userInfo.append('</tr>');
215 for (region in data) {
216 for (user in data[region]) {
217 if (user != 'queues') {
218 userInfo.append('<tr>');
219 userInfo.append('<td>' + region + '</td>');
220 userInfo.append('<td>' + data[region][user].Name + '</td>');
221 if (data[region][user].isRoot == 'true') {
222 userInfo.append('<td>root</td>');
223 }
224 else {
225 userInfo.append('<td>child</td>');
226 }
227 userInfo.append('<td>' + data[region][user].position + '</td>');
228 userInfo.append('</tr>');
229 }
230 }
231 }
232 userInfo.append('</table>');
233 $('#SimSessionStats').empty();
234 $('#SimSessionStats').append(userInfo.toString());
235}
236
237function DebugLog(msg) {
238 $("#DEBUG").append('<div>' + msg + '</div>');
239 $("#DEBUG").show();
240}
241
242function StringBuffer() {
243 this.__strings__ = new Array;
244}
245StringBuffer.prototype.append = function(str) {
246 this.__strings__.push(str);
247}
248StringBuffer.prototype.toString = function() {
249 return this.__strings__.join("");
250}
251
252</script>
253</head>
254<body id="SimBody">
255<div id="SimHeader"></div>
256<div id="SimContent">
257
258<!-- ============================================== -->
259<div class="SimSectionContainer">
260<a class="SimSectionHeader" href="#">Simulator Stats</a>
261<div id="SimSimStats" class="SimSection">
262</div> <!-- SimSimStats -->
263</div> <!-- SimSectionContainer -->
264
265<!-- ============================================== -->
266<div class="SimSectionContainer">
267<a class="SimSectionHeader" href="#">Region Stats</a>
268<div id="SimRegionStats" class="SimSection">
269</div> <!-- SimRegionStats -->
270</div> <!-- SimSectionContainer -->
271
272<!-- ============================================== -->
273<div class="SimSectionContainer">
274<a class="SimSectionHeader" href="#">Sessions</a>
275<div id="SimSessionStats" class="SimSection">
276</div> <!-- SimSessionStats -->
277</div> <!-- SimSectionContainer -->
278
279<!-- ============================================== -->
280<div class="SimSectionContainer">
281<a class="SimSectionHeader" href="#">Log File</a>
282<div id="SimLogFile" class="SimSection">
283</div> <!-- SimLogFile -->
284</div> <!-- SimSectionContainer -->
285
286<!-- ============================================== -->
287</div> <!-- SimContent -->
288<div id="DEBUG"></div>
289<div id="SimFooter"></div>
290</body>
291</html>
diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll
index 2ae1c75..de4f95a 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 d4852a5..674a08a 100755
--- a/bin/lib32/libBulletSim.so
+++ b/bin/lib32/libBulletSim.so
Binary files differ
diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll
index 77cf7e3..1c55b19 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 4ec62b2..e2fc8bd 100755
--- a/bin/lib64/libBulletSim.so
+++ b/bin/lib64/libBulletSim.so
Binary files differ
diff --git a/doc/README b/doc/README
new file mode 100644
index 0000000..9c95557
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,20 @@
1README
2
3This directory does not currently contain any OpenSimulator user level documentation. Such
4documentation can be found at
5
6http://opensimulator.org
7
8instead.
9
10Rather, this directory can contain source-code documentation as generated via the doxygen package.
11
12To do this, either execute
13
14doxygen doxygen.conf
15
16on the command line or run the target
17
18nant doxygen
19
20if you have nant installed.
diff --git a/doc/doxygen.conf b/doc/doxygen.conf
index 3712dfa..148de9c 100644
--- a/doc/doxygen.conf
+++ b/doc/doxygen.conf
@@ -1,1356 +1,290 @@
1# Doxyfile 1.5.5 1# Doxyfile 1.8.2
2
3# This file describes the settings to be used by the documentation system
4# doxygen (www.doxygen.org) for a project
5#
6# All text after a hash (#) is considered a comment and will be ignored
7# The format is:
8# TAG = value [value, ...]
9# For lists items can also be appended using:
10# TAG += value [value, ...]
11# Values that contain spaces should be placed between quotes (" ")
12 2
13#--------------------------------------------------------------------------- 3#---------------------------------------------------------------------------
14# Project related configuration options 4# Project related configuration options
15#--------------------------------------------------------------------------- 5#---------------------------------------------------------------------------
16
17# This tag specifies the encoding used for all characters in the config file
18# that follow. The default is UTF-8 which is also the encoding used for all
19# text before the first occurrence of this tag. Doxygen uses libiconv (or the
20# iconv built into libc) for the transcoding. See
21# http://www.gnu.org/software/libiconv for the list of possible encodings.
22
23DOXYFILE_ENCODING = UTF-8 6DOXYFILE_ENCODING = UTF-8
24
25# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
26# by quotes) that should identify the project.
27
28PROJECT_NAME = OpenSim 7PROJECT_NAME = OpenSim
29 8PROJECT_NUMBER = GIT
30# The PROJECT_NUMBER tag can be used to enter a project or revision number. 9PROJECT_BRIEF =
31# This could be handy for archiving the generated documentation or 10PROJECT_LOGO =
32# if some version control system is used.
33
34PROJECT_NUMBER = SVN
35
36# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
37# base path where the generated documentation will be put.
38# If a relative path is entered, it will be relative to the location
39# where doxygen was started. If left blank the current directory will be used.
40
41OUTPUT_DIRECTORY = 11OUTPUT_DIRECTORY =
42
43# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
44# 4096 sub-directories (in 2 levels) under the output directory of each output
45# format and will distribute the generated files over these directories.
46# Enabling this option can be useful when feeding doxygen a huge amount of
47# source files, where putting all generated files in the same directory would
48# otherwise cause performance problems for the file system.
49
50CREATE_SUBDIRS = NO 12CREATE_SUBDIRS = NO
51
52# The OUTPUT_LANGUAGE tag is used to specify the language in which all
53# documentation generated by doxygen is written. Doxygen will use this
54# information to generate all constant output in the proper language.
55# The default language is English, other supported languages are:
56# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
57# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
58# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
59# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
60# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
61# and Ukrainian.
62
63OUTPUT_LANGUAGE = English 13OUTPUT_LANGUAGE = English
64
65# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
66# include brief member descriptions after the members that are listed in
67# the file and class documentation (similar to JavaDoc).
68# Set to NO to disable this.
69
70BRIEF_MEMBER_DESC = YES 14BRIEF_MEMBER_DESC = YES
71
72# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
73# the brief description of a member or function before the detailed description.
74# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
75# brief descriptions will be completely suppressed.
76
77REPEAT_BRIEF = YES 15REPEAT_BRIEF = YES
78 16ABBREVIATE_BRIEF =
79# This tag implements a quasi-intelligent brief description abbreviator
80# that is used to form the text in various listings. Each string
81# in this list, if found as the leading text of the brief description, will be
82# stripped from the text and the result after processing the whole list, is
83# used as the annotated text. Otherwise, the brief description is used as-is.
84# If left blank, the following values are used ("$name" is automatically
85# replaced with the name of the entity): "The $name class" "The $name widget"
86# "The $name file" "is" "provides" "specifies" "contains"
87# "represents" "a" "an" "the"
88
89ABBREVIATE_BRIEF =
90
91# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
92# Doxygen will generate a detailed section even if there is only a brief
93# description.
94
95ALWAYS_DETAILED_SEC = NO 17ALWAYS_DETAILED_SEC = NO
96
97# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
98# inherited members of a class in the documentation of that class as if those
99# members were ordinary class members. Constructors, destructors and assignment
100# operators of the base classes will not be shown.
101
102INLINE_INHERITED_MEMB = NO 18INLINE_INHERITED_MEMB = NO
103
104# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
105# path before files name in the file list and in the header files. If set
106# to NO the shortest path that makes the file name unique will be used.
107
108FULL_PATH_NAMES = YES 19FULL_PATH_NAMES = YES
109 20STRIP_FROM_PATH =
110# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 21STRIP_FROM_INC_PATH =
111# can be used to strip a user-defined part of the path. Stripping is
112# only done if one of the specified strings matches the left-hand part of
113# the path. The tag can be used to show relative paths in the file list.
114# If left blank the directory from which doxygen is run is used as the
115# path to strip.
116
117STRIP_FROM_PATH =
118
119# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
120# the path mentioned in the documentation of a class, which tells
121# the reader which header file to include in order to use a class.
122# If left blank only the name of the header file containing the class
123# definition is used. Otherwise one should specify the include paths that
124# are normally passed to the compiler using the -I flag.
125
126STRIP_FROM_INC_PATH =
127
128# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
129# (but less readable) file names. This can be useful is your file systems
130# doesn't support long names like on DOS, Mac, or CD-ROM.
131
132SHORT_NAMES = NO 22SHORT_NAMES = NO
133
134# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
135# will interpret the first line (until the first dot) of a JavaDoc-style
136# comment as the brief description. If set to NO, the JavaDoc
137# comments will behave just like regular Qt-style comments
138# (thus requiring an explicit @brief command for a brief description.)
139
140JAVADOC_AUTOBRIEF = NO 23JAVADOC_AUTOBRIEF = NO
141
142# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
143# interpret the first line (until the first dot) of a Qt-style
144# comment as the brief description. If set to NO, the comments
145# will behave just like regular Qt-style comments (thus requiring
146# an explicit \brief command for a brief description.)
147
148QT_AUTOBRIEF = NO 24QT_AUTOBRIEF = NO
149
150# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
151# treat a multi-line C++ special comment block (i.e. a block of //! or ///
152# comments) as a brief description. This used to be the default behaviour.
153# The new default is to treat a multi-line C++ comment block as a detailed
154# description. Set this tag to YES if you prefer the old behaviour instead.
155
156MULTILINE_CPP_IS_BRIEF = NO 25MULTILINE_CPP_IS_BRIEF = NO
157
158# If the DETAILS_AT_TOP tag is set to YES then Doxygen
159# will output the detailed description near the top, like JavaDoc.
160# If set to NO, the detailed description appears after the member
161# documentation.
162
163DETAILS_AT_TOP = NO
164
165# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
166# member inherits the documentation from any documented member that it
167# re-implements.
168
169INHERIT_DOCS = YES 26INHERIT_DOCS = YES
170
171# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
172# a new page for each member. If set to NO, the documentation of a member will
173# be part of the file/class/namespace that contains it.
174
175SEPARATE_MEMBER_PAGES = NO 27SEPARATE_MEMBER_PAGES = NO
176
177# The TAB_SIZE tag can be used to set the number of spaces in a tab.
178# Doxygen uses this value to replace tabs by spaces in code fragments.
179
180TAB_SIZE = 8 28TAB_SIZE = 8
181 29ALIASES =
182# This tag can be used to specify a number of aliases that acts 30TCL_SUBST =
183# as commands in the documentation. An alias has the form "name=value".
184# For example adding "sideeffect=\par Side Effects:\n" will allow you to
185# put the command \sideeffect (or @sideeffect) in the documentation, which
186# will result in a user-defined paragraph with heading "Side Effects:".
187# You can put \n's in the value part of an alias to insert newlines.
188
189ALIASES =
190
191# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
192# sources only. Doxygen will then generate output that is more tailored for C.
193# For instance, some of the names that are used will be different. The list
194# of all members will be omitted, etc.
195
196OPTIMIZE_OUTPUT_FOR_C = NO 31OPTIMIZE_OUTPUT_FOR_C = NO
197
198# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
199# sources only. Doxygen will then generate output that is more tailored for
200# Java. For instance, namespaces will be presented as packages, qualified
201# scopes will look different, etc.
202
203OPTIMIZE_OUTPUT_JAVA = NO 32OPTIMIZE_OUTPUT_JAVA = NO
204
205# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
206# sources only. Doxygen will then generate output that is more tailored for
207# Fortran.
208
209OPTIMIZE_FOR_FORTRAN = NO 33OPTIMIZE_FOR_FORTRAN = NO
210
211# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
212# sources. Doxygen will then generate output that is tailored for
213# VHDL.
214
215OPTIMIZE_OUTPUT_VHDL = NO 34OPTIMIZE_OUTPUT_VHDL = NO
216 35EXTENSION_MAPPING =
217# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 36MARKDOWN_SUPPORT = YES
218# to include (a tag file for) the STL sources as input, then you should 37AUTOLINK_SUPPORT = YES
219# set this tag to YES in order to let doxygen match functions declarations and
220# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
221# func(std::string) {}). This also make the inheritance and collaboration
222# diagrams that involve STL classes more complete and accurate.
223
224BUILTIN_STL_SUPPORT = NO 38BUILTIN_STL_SUPPORT = NO
225
226# If you use Microsoft's C++/CLI language, you should set this option to YES to
227# enable parsing support.
228
229CPP_CLI_SUPPORT = NO 39CPP_CLI_SUPPORT = NO
230
231# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
232# Doxygen will parse them like normal C++ but will assume all classes use public
233# instead of private inheritance when no explicit protection keyword is present.
234
235SIP_SUPPORT = NO 40SIP_SUPPORT = NO
236 41IDL_PROPERTY_SUPPORT = YES
237# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
238# tag is set to YES, then doxygen will reuse the documentation of the first
239# member in the group (if any) for the other members of the group. By default
240# all members of a group must be documented explicitly.
241
242DISTRIBUTE_GROUP_DOC = NO 42DISTRIBUTE_GROUP_DOC = NO
243
244# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
245# the same type (for instance a group of public functions) to be put as a
246# subgroup of that type (e.g. under the Public Functions section). Set it to
247# NO to prevent subgrouping. Alternatively, this can be done per class using
248# the \nosubgrouping command.
249
250SUBGROUPING = YES 43SUBGROUPING = YES
251 44INLINE_GROUPED_CLASSES = NO
252# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 45INLINE_SIMPLE_STRUCTS = NO
253# is documented as struct, union, or enum with the name of the typedef. So
254# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
255# with name TypeT. When disabled the typedef will appear as a member of a file,
256# namespace, or class. And the struct will be named TypeS. This can typically
257# be useful for C code in case the coding convention dictates that all compound
258# types are typedef'ed and only the typedef is referenced, never the tag name.
259
260TYPEDEF_HIDES_STRUCT = NO 46TYPEDEF_HIDES_STRUCT = NO
261 47SYMBOL_CACHE_SIZE = 0
48LOOKUP_CACHE_SIZE = 0
262#--------------------------------------------------------------------------- 49#---------------------------------------------------------------------------
263# Build related configuration options 50# Build related configuration options
264#--------------------------------------------------------------------------- 51#---------------------------------------------------------------------------
265
266# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
267# documentation are documented, even if no documentation was available.
268# Private class members and static file members will be hidden unless
269# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
270
271EXTRACT_ALL = YES 52EXTRACT_ALL = YES
272
273# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
274# will be included in the documentation.
275
276EXTRACT_PRIVATE = NO 53EXTRACT_PRIVATE = NO
277 54EXTRACT_PACKAGE = NO
278# If the EXTRACT_STATIC tag is set to YES all static members of a file
279# will be included in the documentation.
280
281EXTRACT_STATIC = NO 55EXTRACT_STATIC = NO
282
283# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
284# defined locally in source files will be included in the documentation.
285# If set to NO only classes defined in header files are included.
286
287EXTRACT_LOCAL_CLASSES = YES 56EXTRACT_LOCAL_CLASSES = YES
288
289# This flag is only useful for Objective-C code. When set to YES local
290# methods, which are defined in the implementation section but not in
291# the interface are included in the documentation.
292# If set to NO (the default) only methods in the interface are included.
293
294EXTRACT_LOCAL_METHODS = NO 57EXTRACT_LOCAL_METHODS = NO
295
296# If this flag is set to YES, the members of anonymous namespaces will be
297# extracted and appear in the documentation as a namespace called
298# 'anonymous_namespace{file}', where file will be replaced with the base
299# name of the file that contains the anonymous namespace. By default
300# anonymous namespace are hidden.
301
302EXTRACT_ANON_NSPACES = NO 58EXTRACT_ANON_NSPACES = NO
303
304# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
305# undocumented members of documented classes, files or namespaces.
306# If set to NO (the default) these members will be included in the
307# various overviews, but no documentation section is generated.
308# This option has no effect if EXTRACT_ALL is enabled.
309
310HIDE_UNDOC_MEMBERS = NO 59HIDE_UNDOC_MEMBERS = NO
311
312# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
313# undocumented classes that are normally visible in the class hierarchy.
314# If set to NO (the default) these classes will be included in the various
315# overviews. This option has no effect if EXTRACT_ALL is enabled.
316
317HIDE_UNDOC_CLASSES = NO 60HIDE_UNDOC_CLASSES = NO
318
319# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
320# friend (class|struct|union) declarations.
321# If set to NO (the default) these declarations will be included in the
322# documentation.
323
324HIDE_FRIEND_COMPOUNDS = NO 61HIDE_FRIEND_COMPOUNDS = NO
325
326# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
327# documentation blocks found inside the body of a function.
328# If set to NO (the default) these blocks will be appended to the
329# function's detailed documentation block.
330
331HIDE_IN_BODY_DOCS = NO 62HIDE_IN_BODY_DOCS = NO
332
333# The INTERNAL_DOCS tag determines if documentation
334# that is typed after a \internal command is included. If the tag is set
335# to NO (the default) then the documentation will be excluded.
336# Set it to YES to include the internal documentation.
337
338INTERNAL_DOCS = NO 63INTERNAL_DOCS = NO
339
340# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
341# file names in lower-case letters. If set to YES upper-case letters are also
342# allowed. This is useful if you have classes or files whose names only differ
343# in case and if your file system supports case sensitive file names. Windows
344# and Mac users are advised to set this option to NO.
345
346CASE_SENSE_NAMES = YES 64CASE_SENSE_NAMES = YES
347
348# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
349# will show members with their full class and namespace scopes in the
350# documentation. If set to YES the scope will be hidden.
351
352HIDE_SCOPE_NAMES = NO 65HIDE_SCOPE_NAMES = NO
353
354# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
355# will put a list of the files that are included by a file in the documentation
356# of that file.
357
358SHOW_INCLUDE_FILES = YES 66SHOW_INCLUDE_FILES = YES
359 67FORCE_LOCAL_INCLUDES = NO
360# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
361# is inserted in the documentation for inline members.
362
363INLINE_INFO = YES 68INLINE_INFO = YES
364
365# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
366# will sort the (detailed) documentation of file and class members
367# alphabetically by member name. If set to NO the members will appear in
368# declaration order.
369
370SORT_MEMBER_DOCS = YES 69SORT_MEMBER_DOCS = YES
371
372# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
373# brief documentation of file, namespace and class members alphabetically
374# by member name. If set to NO (the default) the members will appear in
375# declaration order.
376
377SORT_BRIEF_DOCS = NO 70SORT_BRIEF_DOCS = NO
378 71SORT_MEMBERS_CTORS_1ST = NO
379# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
380# hierarchy of group names into alphabetical order. If set to NO (the default)
381# the group names will appear in their defined order.
382
383SORT_GROUP_NAMES = NO 72SORT_GROUP_NAMES = NO
384
385# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
386# sorted by fully-qualified names, including namespaces. If set to
387# NO (the default), the class list will be sorted only by class name,
388# not including the namespace part.
389# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
390# Note: This option applies only to the class list, not to the
391# alphabetical list.
392
393SORT_BY_SCOPE_NAME = NO 73SORT_BY_SCOPE_NAME = NO
394 74STRICT_PROTO_MATCHING = NO
395# The GENERATE_TODOLIST tag can be used to enable (YES) or
396# disable (NO) the todo list. This list is created by putting \todo
397# commands in the documentation.
398
399GENERATE_TODOLIST = YES 75GENERATE_TODOLIST = YES
400
401# The GENERATE_TESTLIST tag can be used to enable (YES) or
402# disable (NO) the test list. This list is created by putting \test
403# commands in the documentation.
404
405GENERATE_TESTLIST = YES 76GENERATE_TESTLIST = YES
406
407# The GENERATE_BUGLIST tag can be used to enable (YES) or
408# disable (NO) the bug list. This list is created by putting \bug
409# commands in the documentation.
410
411GENERATE_BUGLIST = YES 77GENERATE_BUGLIST = YES
412
413# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
414# disable (NO) the deprecated list. This list is created by putting
415# \deprecated commands in the documentation.
416
417GENERATE_DEPRECATEDLIST= YES 78GENERATE_DEPRECATEDLIST= YES
418 79ENABLED_SECTIONS =
419# The ENABLED_SECTIONS tag can be used to enable conditional
420# documentation sections, marked by \if sectionname ... \endif.
421
422ENABLED_SECTIONS =
423
424# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
425# the initial value of a variable or define consists of for it to appear in
426# the documentation. If the initializer consists of more lines than specified
427# here it will be hidden. Use a value of 0 to hide initializers completely.
428# The appearance of the initializer of individual variables and defines in the
429# documentation can be controlled using \showinitializer or \hideinitializer
430# command in the documentation regardless of this setting.
431
432MAX_INITIALIZER_LINES = 30 80MAX_INITIALIZER_LINES = 30
433
434# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
435# at the bottom of the documentation of classes and structs. If set to YES the
436# list will mention the files that were used to generate the documentation.
437
438SHOW_USED_FILES = YES 81SHOW_USED_FILES = YES
439 82SHOW_FILES = YES
440# If the sources in your project are distributed over multiple directories 83SHOW_NAMESPACES = YES
441# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 84FILE_VERSION_FILTER =
442# in the documentation. The default is NO. 85LAYOUT_FILE =
443 86CITE_BIB_FILES =
444SHOW_DIRECTORIES = NO
445
446# The FILE_VERSION_FILTER tag can be used to specify a program or script that
447# doxygen should invoke to get the current version for each file (typically from
448# the version control system). Doxygen will invoke the program by executing (via
449# popen()) the command <command> <input-file>, where <command> is the value of
450# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
451# provided by doxygen. Whatever the program writes to standard output
452# is used as the file version. See the manual for examples.
453
454FILE_VERSION_FILTER =
455
456#--------------------------------------------------------------------------- 87#---------------------------------------------------------------------------
457# configuration options related to warning and progress messages 88# configuration options related to warning and progress messages
458#--------------------------------------------------------------------------- 89#---------------------------------------------------------------------------
459
460# The QUIET tag can be used to turn on/off the messages that are generated
461# by doxygen. Possible values are YES and NO. If left blank NO is used.
462
463QUIET = NO 90QUIET = NO
464
465# The WARNINGS tag can be used to turn on/off the warning messages that are
466# generated by doxygen. Possible values are YES and NO. If left blank
467# NO is used.
468
469WARNINGS = YES 91WARNINGS = YES
470
471# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
472# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
473# automatically be disabled.
474
475WARN_IF_UNDOCUMENTED = YES 92WARN_IF_UNDOCUMENTED = YES
476
477# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
478# potential errors in the documentation, such as not documenting some
479# parameters in a documented function, or documenting parameters that
480# don't exist or using markup commands wrongly.
481
482WARN_IF_DOC_ERROR = YES 93WARN_IF_DOC_ERROR = YES
483
484# This WARN_NO_PARAMDOC option can be abled to get warnings for
485# functions that are documented, but have no documentation for their parameters
486# or return value. If set to NO (the default) doxygen will only warn about
487# wrong or incomplete parameter documentation, but not about the absence of
488# documentation.
489
490WARN_NO_PARAMDOC = NO 94WARN_NO_PARAMDOC = NO
491
492# The WARN_FORMAT tag determines the format of the warning messages that
493# doxygen can produce. The string should contain the $file, $line, and $text
494# tags, which will be replaced by the file and line number from which the
495# warning originated and the warning text. Optionally the format may contain
496# $version, which will be replaced by the version of the file (if it could
497# be obtained via FILE_VERSION_FILTER)
498
499WARN_FORMAT = "$file:$line: $text" 95WARN_FORMAT = "$file:$line: $text"
500 96WARN_LOGFILE = doxygen.error.log
501# The WARN_LOGFILE tag can be used to specify a file to which warning
502# and error messages should be written. If left blank the output is written
503# to stderr.
504
505WARN_LOGFILE =
506
507#--------------------------------------------------------------------------- 97#---------------------------------------------------------------------------
508# configuration options related to the input files 98# configuration options related to the input files
509#--------------------------------------------------------------------------- 99#---------------------------------------------------------------------------
510
511# The INPUT tag can be used to specify the files and/or directories that contain
512# documented source files. You may enter file names like "myfile.cpp" or
513# directories like "/usr/src/myproject". Separate the files or directories
514# with spaces.
515
516INPUT = ../OpenSim 100INPUT = ../OpenSim
517
518# This tag can be used to specify the character encoding of the source files
519# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
520# also the default input encoding. Doxygen uses libiconv (or the iconv built
521# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
522# the list of possible encodings.
523
524INPUT_ENCODING = UTF-8 101INPUT_ENCODING = UTF-8
525 102FILE_PATTERNS =
526# If the value of the INPUT tag contains directories, you can use the
527# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
528# and *.h) to filter out the source-files in the directories. If left
529# blank the following patterns are tested:
530# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
531# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
532
533FILE_PATTERNS =
534
535# The RECURSIVE tag can be used to turn specify whether or not subdirectories
536# should be searched for input files as well. Possible values are YES and NO.
537# If left blank NO is used.
538
539RECURSIVE = YES 103RECURSIVE = YES
540
541# The EXCLUDE tag can be used to specify files and/or directories that should
542# excluded from the INPUT source files. This way you can easily exclude a
543# subdirectory from a directory tree whose root is specified with the INPUT tag.
544
545EXCLUDE = 104EXCLUDE =
546
547# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
548# directories that are symbolic links (a Unix filesystem feature) are excluded
549# from the input.
550
551EXCLUDE_SYMLINKS = NO 105EXCLUDE_SYMLINKS = NO
552 106EXCLUDE_PATTERNS =
553# If the value of the INPUT tag contains directories, you can use the 107EXCLUDE_SYMBOLS =
554# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 108EXAMPLE_PATH =
555# certain files from those directories. Note that the wildcards are matched 109EXAMPLE_PATTERNS =
556# against the file with absolute path, so to exclude all test directories
557# for example use the pattern */test/*
558
559EXCLUDE_PATTERNS =
560
561# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
562# (namespaces, classes, functions, etc.) that should be excluded from the
563# output. The symbol name can be a fully qualified name, a word, or if the
564# wildcard * is used, a substring. Examples: ANamespace, AClass,
565# AClass::ANamespace, ANamespace::*Test
566
567EXCLUDE_SYMBOLS =
568
569# The EXAMPLE_PATH tag can be used to specify one or more files or
570# directories that contain example code fragments that are included (see
571# the \include command).
572
573EXAMPLE_PATH =
574
575# If the value of the EXAMPLE_PATH tag contains directories, you can use the
576# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
577# and *.h) to filter out the source-files in the directories. If left
578# blank all files are included.
579
580EXAMPLE_PATTERNS =
581
582# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
583# searched for input files to be used with the \include or \dontinclude
584# commands irrespective of the value of the RECURSIVE tag.
585# Possible values are YES and NO. If left blank NO is used.
586
587EXAMPLE_RECURSIVE = NO 110EXAMPLE_RECURSIVE = NO
588 111IMAGE_PATH =
589# The IMAGE_PATH tag can be used to specify one or more files or 112INPUT_FILTER =
590# directories that contain image that are included in the documentation (see 113FILTER_PATTERNS =
591# the \image command).
592
593IMAGE_PATH =
594
595# The INPUT_FILTER tag can be used to specify a program that doxygen should
596# invoke to filter for each input file. Doxygen will invoke the filter program
597# by executing (via popen()) the command <filter> <input-file>, where <filter>
598# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
599# input file. Doxygen will then use the output that the filter program writes
600# to standard output. If FILTER_PATTERNS is specified, this tag will be
601# ignored.
602
603INPUT_FILTER =
604
605# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
606# basis. Doxygen will compare the file name with each pattern and apply the
607# filter if there is a match. The filters are a list of the form:
608# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
609# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
610# is applied to all files.
611
612FILTER_PATTERNS =
613
614# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
615# INPUT_FILTER) will be used to filter the input files when producing source
616# files to browse (i.e. when SOURCE_BROWSER is set to YES).
617
618FILTER_SOURCE_FILES = NO 114FILTER_SOURCE_FILES = NO
619 115FILTER_SOURCE_PATTERNS =
620#--------------------------------------------------------------------------- 116#---------------------------------------------------------------------------
621# configuration options related to source browsing 117# configuration options related to source browsing
622#--------------------------------------------------------------------------- 118#---------------------------------------------------------------------------
623
624# If the SOURCE_BROWSER tag is set to YES then a list of source files will
625# be generated. Documented entities will be cross-referenced with these sources.
626# Note: To get rid of all source code in the generated output, make sure also
627# VERBATIM_HEADERS is set to NO.
628
629SOURCE_BROWSER = NO 119SOURCE_BROWSER = NO
630
631# Setting the INLINE_SOURCES tag to YES will include the body
632# of functions and classes directly in the documentation.
633
634INLINE_SOURCES = NO 120INLINE_SOURCES = NO
635
636# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
637# doxygen to hide any special comment blocks from generated source code
638# fragments. Normal C and C++ comments will always remain visible.
639
640STRIP_CODE_COMMENTS = YES 121STRIP_CODE_COMMENTS = YES
641
642# If the REFERENCED_BY_RELATION tag is set to YES (the default)
643# then for each documented function all documented
644# functions referencing it will be listed.
645
646REFERENCED_BY_RELATION = NO 122REFERENCED_BY_RELATION = NO
647
648# If the REFERENCES_RELATION tag is set to YES (the default)
649# then for each documented function all documented entities
650# called/used by that function will be listed.
651
652REFERENCES_RELATION = NO 123REFERENCES_RELATION = NO
653
654# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
655# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
656# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
657# link to the source code. Otherwise they will link to the documentstion.
658
659REFERENCES_LINK_SOURCE = YES 124REFERENCES_LINK_SOURCE = YES
660
661# If the USE_HTAGS tag is set to YES then the references to source code
662# will point to the HTML generated by the htags(1) tool instead of doxygen
663# built-in source browser. The htags tool is part of GNU's global source
664# tagging system (see http://www.gnu.org/software/global/global.html). You
665# will need version 4.8.6 or higher.
666
667USE_HTAGS = NO 125USE_HTAGS = NO
668
669# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
670# will generate a verbatim copy of the header file for each class for
671# which an include is specified. Set to NO to disable this.
672
673VERBATIM_HEADERS = YES 126VERBATIM_HEADERS = YES
674
675#--------------------------------------------------------------------------- 127#---------------------------------------------------------------------------
676# configuration options related to the alphabetical class index 128# configuration options related to the alphabetical class index
677#--------------------------------------------------------------------------- 129#---------------------------------------------------------------------------
678
679# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
680# of all compounds will be generated. Enable this if the project
681# contains a lot of classes, structs, unions or interfaces.
682
683ALPHABETICAL_INDEX = NO 130ALPHABETICAL_INDEX = NO
684
685# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
686# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
687# in which this list will be split (can be a number in the range [1..20])
688
689COLS_IN_ALPHA_INDEX = 5 131COLS_IN_ALPHA_INDEX = 5
690 132IGNORE_PREFIX =
691# In case all classes in a project start with a common prefix, all
692# classes will be put under the same header in the alphabetical index.
693# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
694# should be ignored while generating the index headers.
695
696IGNORE_PREFIX =
697
698#--------------------------------------------------------------------------- 133#---------------------------------------------------------------------------
699# configuration options related to the HTML output 134# configuration options related to the HTML output
700#--------------------------------------------------------------------------- 135#---------------------------------------------------------------------------
701
702# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
703# generate HTML output.
704
705GENERATE_HTML = YES 136GENERATE_HTML = YES
706
707# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
708# If a relative path is entered the value of OUTPUT_DIRECTORY will be
709# put in front of it. If left blank `html' will be used as the default path.
710
711HTML_OUTPUT = html 137HTML_OUTPUT = html
712
713# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
714# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
715# doxygen will generate files with .html extension.
716
717HTML_FILE_EXTENSION = .html 138HTML_FILE_EXTENSION = .html
718 139HTML_HEADER =
719# The HTML_HEADER tag can be used to specify a personal HTML header for 140HTML_FOOTER =
720# each generated HTML page. If it is left blank doxygen will generate a 141HTML_STYLESHEET =
721# standard header. 142HTML_EXTRA_STYLESHEET =
722 143HTML_EXTRA_FILES =
723HTML_HEADER = 144HTML_COLORSTYLE_HUE = 220
724 145HTML_COLORSTYLE_SAT = 100
725# The HTML_FOOTER tag can be used to specify a personal HTML footer for 146HTML_COLORSTYLE_GAMMA = 80
726# each generated HTML page. If it is left blank doxygen will generate a 147HTML_TIMESTAMP = YES
727# standard footer.
728
729HTML_FOOTER =
730
731# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
732# style sheet that is used by each HTML page. It can be used to
733# fine-tune the look of the HTML output. If the tag is left blank doxygen
734# will generate a default style sheet. Note that doxygen will try to copy
735# the style sheet file to the HTML output directory, so don't put your own
736# stylesheet in the HTML output directory as well, or it will be erased!
737
738HTML_STYLESHEET =
739
740# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
741# files or namespaces will be aligned in HTML using tables. If set to
742# NO a bullet list will be used.
743
744HTML_ALIGN_MEMBERS = YES
745
746# If the GENERATE_HTMLHELP tag is set to YES, additional index files
747# will be generated that can be used as input for tools like the
748# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
749# of the generated HTML documentation.
750
751GENERATE_HTMLHELP = NO
752
753# If the GENERATE_DOCSET tag is set to YES, additional index files
754# will be generated that can be used as input for Apple's Xcode 3
755# integrated development environment, introduced with OSX 10.5 (Leopard).
756# To create a documentation set, doxygen will generate a Makefile in the
757# HTML output directory. Running make will produce the docset in that
758# directory and running "make install" will install the docset in
759# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
760# it at startup.
761
762GENERATE_DOCSET = NO
763
764# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
765# feed. A documentation feed provides an umbrella under which multiple
766# documentation sets from a single provider (such as a company or product suite)
767# can be grouped.
768
769DOCSET_FEEDNAME = "Doxygen generated docs"
770
771# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
772# should uniquely identify the documentation set bundle. This should be a
773# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
774# will append .docset to the name.
775
776DOCSET_BUNDLE_ID = org.doxygen.Project
777
778# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
779# documentation will contain sections that can be hidden and shown after the
780# page has loaded. For this to work a browser that supports
781# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
782# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
783
784HTML_DYNAMIC_SECTIONS = NO 148HTML_DYNAMIC_SECTIONS = NO
785 149HTML_INDEX_NUM_ENTRIES = 100
786# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 150GENERATE_DOCSET = NO
787# be used to specify the file name of the resulting .chm file. You 151DOCSET_FEEDNAME = "OpenSimulator docs"
788# can add a path in front of the file if the result should not be 152DOCSET_BUNDLE_ID = org.opensimulator.OpenSim
789# written to the html output directory. 153DOCSET_PUBLISHER_ID = org.opensimulator.OpenSim
790 154DOCSET_PUBLISHER_NAME = OpenSim
791CHM_FILE = 155GENERATE_HTMLHELP = NO
792 156CHM_FILE =
793# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 157HHC_LOCATION =
794# be used to specify the location (absolute path including file name) of
795# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
796# the HTML help compiler on the generated index.hhp.
797
798HHC_LOCATION =
799
800# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
801# controls if a separate .chi index file is generated (YES) or that
802# it should be included in the master .chm file (NO).
803
804GENERATE_CHI = NO 158GENERATE_CHI = NO
805 159CHM_INDEX_ENCODING =
806# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
807# controls whether a binary table of contents is generated (YES) or a
808# normal table of contents (NO) in the .chm file.
809
810BINARY_TOC = NO 160BINARY_TOC = NO
811
812# The TOC_EXPAND flag can be set to YES to add extra items for group members
813# to the contents of the HTML help documentation and to the tree view.
814
815TOC_EXPAND = NO 161TOC_EXPAND = NO
816 162GENERATE_QHP = NO
817# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 163QCH_FILE =
818# top of each HTML page. The value NO (the default) enables the index and 164QHP_NAMESPACE = org.opensimulator.OpenSim
819# the value YES disables it. 165QHP_VIRTUAL_FOLDER = doc
820 166QHP_CUST_FILTER_NAME =
167QHP_CUST_FILTER_ATTRS =
168QHP_SECT_FILTER_ATTRS =
169QHG_LOCATION =
170GENERATE_ECLIPSEHELP = NO
171ECLIPSE_DOC_ID = org.opensimulator.OpenSim
821DISABLE_INDEX = NO 172DISABLE_INDEX = NO
822
823# This tag can be used to set the number of enum values (range [1..20])
824# that doxygen will group on one line in the generated HTML documentation.
825
826ENUM_VALUES_PER_LINE = 4
827
828# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
829# generated containing a tree-like index structure (just like the one that
830# is generated for HTML Help). For this to work a browser that supports
831# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
832# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
833# probably better off using the HTML help feature.
834
835GENERATE_TREEVIEW = NO 173GENERATE_TREEVIEW = NO
836 174ENUM_VALUES_PER_LINE = 4
837# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
838# used to set the initial width (in pixels) of the frame in which the tree
839# is shown.
840
841TREEVIEW_WIDTH = 250 175TREEVIEW_WIDTH = 250
842 176EXT_LINKS_IN_WINDOW = NO
177FORMULA_FONTSIZE = 10
178FORMULA_TRANSPARENT = YES
179USE_MATHJAX = NO
180MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
181MATHJAX_EXTENSIONS =
182SEARCHENGINE = YES
183SERVER_BASED_SEARCH = NO
843#--------------------------------------------------------------------------- 184#---------------------------------------------------------------------------
844# configuration options related to the LaTeX output 185# configuration options related to the LaTeX output
845#--------------------------------------------------------------------------- 186#---------------------------------------------------------------------------
846
847# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
848# generate Latex output.
849
850GENERATE_LATEX = NO 187GENERATE_LATEX = NO
851
852# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
853# If a relative path is entered the value of OUTPUT_DIRECTORY will be
854# put in front of it. If left blank `latex' will be used as the default path.
855
856LATEX_OUTPUT = latex 188LATEX_OUTPUT = latex
857
858# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
859# invoked. If left blank `latex' will be used as the default command name.
860
861LATEX_CMD_NAME = latex 189LATEX_CMD_NAME = latex
862
863# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
864# generate index for LaTeX. If left blank `makeindex' will be used as the
865# default command name.
866
867MAKEINDEX_CMD_NAME = makeindex 190MAKEINDEX_CMD_NAME = makeindex
868
869# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
870# LaTeX documents. This may be useful for small projects and may help to
871# save some trees in general.
872
873COMPACT_LATEX = NO 191COMPACT_LATEX = NO
874
875# The PAPER_TYPE tag can be used to set the paper type that is used
876# by the printer. Possible values are: a4, a4wide, letter, legal and
877# executive. If left blank a4wide will be used.
878
879PAPER_TYPE = a4wide 192PAPER_TYPE = a4wide
880 193EXTRA_PACKAGES =
881# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 194LATEX_HEADER =
882# packages that should be included in the LaTeX output. 195LATEX_FOOTER =
883
884EXTRA_PACKAGES =
885
886# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
887# the generated latex document. The header should contain everything until
888# the first chapter. If it is left blank doxygen will generate a
889# standard header. Notice: only use this tag if you know what you are doing!
890
891LATEX_HEADER =
892
893# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
894# is prepared for conversion to pdf (using ps2pdf). The pdf file will
895# contain links (just like the HTML output) instead of page references
896# This makes the output suitable for online browsing using a pdf viewer.
897
898PDF_HYPERLINKS = YES 196PDF_HYPERLINKS = YES
899
900# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
901# plain latex in the generated Makefile. Set this option to YES to get a
902# higher quality PDF documentation.
903
904USE_PDFLATEX = YES 197USE_PDFLATEX = YES
905
906# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
907# command to the generated LaTeX files. This will instruct LaTeX to keep
908# running if errors occur, instead of asking the user for help.
909# This option is also used when generating formulas in HTML.
910
911LATEX_BATCHMODE = NO 198LATEX_BATCHMODE = NO
912
913# If LATEX_HIDE_INDICES is set to YES then doxygen will not
914# include the index chapters (such as File Index, Compound Index, etc.)
915# in the output.
916
917LATEX_HIDE_INDICES = NO 199LATEX_HIDE_INDICES = NO
918 200LATEX_SOURCE_CODE = NO
201LATEX_BIB_STYLE = plain
919#--------------------------------------------------------------------------- 202#---------------------------------------------------------------------------
920# configuration options related to the RTF output 203# configuration options related to the RTF output
921#--------------------------------------------------------------------------- 204#---------------------------------------------------------------------------
922
923# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
924# The RTF output is optimized for Word 97 and may not look very pretty with
925# other RTF readers or editors.
926
927GENERATE_RTF = NO 205GENERATE_RTF = NO
928
929# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
930# If a relative path is entered the value of OUTPUT_DIRECTORY will be
931# put in front of it. If left blank `rtf' will be used as the default path.
932
933RTF_OUTPUT = rtf 206RTF_OUTPUT = rtf
934
935# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
936# RTF documents. This may be useful for small projects and may help to
937# save some trees in general.
938
939COMPACT_RTF = NO 207COMPACT_RTF = NO
940
941# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
942# will contain hyperlink fields. The RTF file will
943# contain links (just like the HTML output) instead of page references.
944# This makes the output suitable for online browsing using WORD or other
945# programs which support those fields.
946# Note: wordpad (write) and others do not support links.
947
948RTF_HYPERLINKS = NO 208RTF_HYPERLINKS = NO
949 209RTF_STYLESHEET_FILE =
950# Load stylesheet definitions from file. Syntax is similar to doxygen's 210RTF_EXTENSIONS_FILE =
951# config file, i.e. a series of assignments. You only have to provide
952# replacements, missing definitions are set to their default value.
953
954RTF_STYLESHEET_FILE =
955
956# Set optional variables used in the generation of an rtf document.
957# Syntax is similar to doxygen's config file.
958
959RTF_EXTENSIONS_FILE =
960
961#--------------------------------------------------------------------------- 211#---------------------------------------------------------------------------
962# configuration options related to the man page output 212# configuration options related to the man page output
963#--------------------------------------------------------------------------- 213#---------------------------------------------------------------------------
964
965# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
966# generate man pages
967
968GENERATE_MAN = NO 214GENERATE_MAN = NO
969
970# The MAN_OUTPUT tag is used to specify where the man pages will be put.
971# If a relative path is entered the value of OUTPUT_DIRECTORY will be
972# put in front of it. If left blank `man' will be used as the default path.
973
974MAN_OUTPUT = man 215MAN_OUTPUT = man
975
976# The MAN_EXTENSION tag determines the extension that is added to
977# the generated man pages (default is the subroutine's section .3)
978
979MAN_EXTENSION = .3 216MAN_EXTENSION = .3
980
981# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
982# then it will generate one additional man file for each entity
983# documented in the real man page(s). These additional files
984# only source the real man page, but without them the man command
985# would be unable to find the correct page. The default is NO.
986
987MAN_LINKS = NO 217MAN_LINKS = NO
988
989#--------------------------------------------------------------------------- 218#---------------------------------------------------------------------------
990# configuration options related to the XML output 219# configuration options related to the XML output
991#--------------------------------------------------------------------------- 220#---------------------------------------------------------------------------
992
993# If the GENERATE_XML tag is set to YES Doxygen will
994# generate an XML file that captures the structure of
995# the code including all documentation.
996
997GENERATE_XML = NO 221GENERATE_XML = NO
998
999# The XML_OUTPUT tag is used to specify where the XML pages will be put.
1000# If a relative path is entered the value of OUTPUT_DIRECTORY will be
1001# put in front of it. If left blank `xml' will be used as the default path.
1002
1003XML_OUTPUT = xml 222XML_OUTPUT = xml
1004 223XML_SCHEMA =
1005# The XML_SCHEMA tag can be used to specify an XML schema, 224XML_DTD =
1006# which can be used by a validating XML parser to check the
1007# syntax of the XML files.
1008
1009XML_SCHEMA =
1010
1011# The XML_DTD tag can be used to specify an XML DTD,
1012# which can be used by a validating XML parser to check the
1013# syntax of the XML files.
1014
1015XML_DTD =
1016
1017# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
1018# dump the program listings (including syntax highlighting
1019# and cross-referencing information) to the XML output. Note that
1020# enabling this will significantly increase the size of the XML output.
1021
1022XML_PROGRAMLISTING = YES 225XML_PROGRAMLISTING = YES
1023
1024#--------------------------------------------------------------------------- 226#---------------------------------------------------------------------------
1025# configuration options for the AutoGen Definitions output 227# configuration options for the AutoGen Definitions output
1026#--------------------------------------------------------------------------- 228#---------------------------------------------------------------------------
1027
1028# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
1029# generate an AutoGen Definitions (see autogen.sf.net) file
1030# that captures the structure of the code including all
1031# documentation. Note that this feature is still experimental
1032# and incomplete at the moment.
1033
1034GENERATE_AUTOGEN_DEF = NO 229GENERATE_AUTOGEN_DEF = NO
1035
1036#--------------------------------------------------------------------------- 230#---------------------------------------------------------------------------
1037# configuration options related to the Perl module output 231# configuration options related to the Perl module output
1038#--------------------------------------------------------------------------- 232#---------------------------------------------------------------------------
1039
1040# If the GENERATE_PERLMOD tag is set to YES Doxygen will
1041# generate a Perl module file that captures the structure of
1042# the code including all documentation. Note that this
1043# feature is still experimental and incomplete at the
1044# moment.
1045
1046GENERATE_PERLMOD = NO 233GENERATE_PERLMOD = NO
1047
1048# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
1049# the necessary Makefile rules, Perl scripts and LaTeX code to be able
1050# to generate PDF and DVI output from the Perl module output.
1051
1052PERLMOD_LATEX = NO 234PERLMOD_LATEX = NO
1053
1054# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
1055# nicely formatted so it can be parsed by a human reader. This is useful
1056# if you want to understand what is going on. On the other hand, if this
1057# tag is set to NO the size of the Perl module output will be much smaller
1058# and Perl will parse it just the same.
1059
1060PERLMOD_PRETTY = YES 235PERLMOD_PRETTY = YES
1061 236PERLMOD_MAKEVAR_PREFIX =
1062# The names of the make variables in the generated doxyrules.make file
1063# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
1064# This is useful so different doxyrules.make files included by the same
1065# Makefile don't overwrite each other's variables.
1066
1067PERLMOD_MAKEVAR_PREFIX =
1068
1069#--------------------------------------------------------------------------- 237#---------------------------------------------------------------------------
1070# Configuration options related to the preprocessor 238# Configuration options related to the preprocessor
1071#--------------------------------------------------------------------------- 239#---------------------------------------------------------------------------
1072
1073# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
1074# evaluate all C-preprocessor directives found in the sources and include
1075# files.
1076
1077ENABLE_PREPROCESSING = YES 240ENABLE_PREPROCESSING = YES
1078
1079# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
1080# names in the source code. If set to NO (the default) only conditional
1081# compilation will be performed. Macro expansion can be done in a controlled
1082# way by setting EXPAND_ONLY_PREDEF to YES.
1083
1084MACRO_EXPANSION = NO 241MACRO_EXPANSION = NO
1085
1086# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
1087# then the macro expansion is limited to the macros specified with the
1088# PREDEFINED and EXPAND_AS_DEFINED tags.
1089
1090EXPAND_ONLY_PREDEF = NO 242EXPAND_ONLY_PREDEF = NO
1091
1092# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
1093# in the INCLUDE_PATH (see below) will be search if a #include is found.
1094
1095SEARCH_INCLUDES = YES 243SEARCH_INCLUDES = YES
1096 244INCLUDE_PATH =
1097# The INCLUDE_PATH tag can be used to specify one or more directories that 245INCLUDE_FILE_PATTERNS =
1098# contain include files that are not input files but should be processed by 246PREDEFINED =
1099# the preprocessor. 247EXPAND_AS_DEFINED =
1100
1101INCLUDE_PATH =
1102
1103# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
1104# patterns (like *.h and *.hpp) to filter out the header-files in the
1105# directories. If left blank, the patterns specified with FILE_PATTERNS will
1106# be used.
1107
1108INCLUDE_FILE_PATTERNS =
1109
1110# The PREDEFINED tag can be used to specify one or more macro names that
1111# are defined before the preprocessor is started (similar to the -D option of
1112# gcc). The argument of the tag is a list of macros of the form: name
1113# or name=definition (no spaces). If the definition and the = are
1114# omitted =1 is assumed. To prevent a macro definition from being
1115# undefined via #undef or recursively expanded use the := operator
1116# instead of the = operator.
1117
1118PREDEFINED =
1119
1120# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
1121# this tag can be used to specify a list of macro names that should be expanded.
1122# The macro definition that is found in the sources will be used.
1123# Use the PREDEFINED tag if you want to use a different macro definition.
1124
1125EXPAND_AS_DEFINED =
1126
1127# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
1128# doxygen's preprocessor will remove all function-like macros that are alone
1129# on a line, have an all uppercase name, and do not end with a semicolon. Such
1130# function macros are typically used for boiler-plate code, and will confuse
1131# the parser if not removed.
1132
1133SKIP_FUNCTION_MACROS = YES 248SKIP_FUNCTION_MACROS = YES
1134
1135#--------------------------------------------------------------------------- 249#---------------------------------------------------------------------------
1136# Configuration::additions related to external references 250# Configuration::additions related to external references
1137#--------------------------------------------------------------------------- 251#---------------------------------------------------------------------------
1138 252TAGFILES =
1139# The TAGFILES option can be used to specify one or more tagfiles. 253GENERATE_TAGFILE =
1140# Optionally an initial location of the external documentation
1141# can be added for each tagfile. The format of a tag file without
1142# this location is as follows:
1143# TAGFILES = file1 file2 ...
1144# Adding location for the tag files is done as follows:
1145# TAGFILES = file1=loc1 "file2 = loc2" ...
1146# where "loc1" and "loc2" can be relative or absolute paths or
1147# URLs. If a location is present for each tag, the installdox tool
1148# does not have to be run to correct the links.
1149# Note that each tag file must have a unique name
1150# (where the name does NOT include the path)
1151# If a tag file is not located in the directory in which doxygen
1152# is run, you must also specify the path to the tagfile here.
1153
1154TAGFILES =
1155
1156# When a file name is specified after GENERATE_TAGFILE, doxygen will create
1157# a tag file that is based on the input files it reads.
1158
1159GENERATE_TAGFILE =
1160
1161# If the ALLEXTERNALS tag is set to YES all external classes will be listed
1162# in the class index. If set to NO only the inherited external classes
1163# will be listed.
1164
1165ALLEXTERNALS = NO 254ALLEXTERNALS = NO
1166
1167# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
1168# in the modules index. If set to NO, only the current project's groups will
1169# be listed.
1170
1171EXTERNAL_GROUPS = YES 255EXTERNAL_GROUPS = YES
1172
1173# The PERL_PATH should be the absolute path and name of the perl script
1174# interpreter (i.e. the result of `which perl').
1175
1176PERL_PATH = /usr/bin/perl 256PERL_PATH = /usr/bin/perl
1177
1178#--------------------------------------------------------------------------- 257#---------------------------------------------------------------------------
1179# Configuration options related to the dot tool 258# Configuration options related to the dot tool
1180#--------------------------------------------------------------------------- 259#---------------------------------------------------------------------------
1181
1182# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
1183# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
1184# or super classes. Setting the tag to NO turns the diagrams off. Note that
1185# this option is superseded by the HAVE_DOT option below. This is only a
1186# fallback. It is recommended to install and use dot, since it yields more
1187# powerful graphs.
1188
1189CLASS_DIAGRAMS = YES 260CLASS_DIAGRAMS = YES
1190 261MSCGEN_PATH =
1191# You can define message sequence charts within doxygen comments using the \msc
1192# command. Doxygen will then run the mscgen tool (see
1193# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
1194# documentation. The MSCGEN_PATH tag allows you to specify the directory where
1195# the mscgen tool resides. If left empty the tool is assumed to be found in the
1196# default search path.
1197
1198MSCGEN_PATH =
1199
1200# If set to YES, the inheritance and collaboration graphs will hide
1201# inheritance and usage relations if the target is undocumented
1202# or is not a class.
1203
1204HIDE_UNDOC_RELATIONS = YES 262HIDE_UNDOC_RELATIONS = YES
1205
1206# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
1207# available from the path. This tool is part of Graphviz, a graph visualization
1208# toolkit from AT&T and Lucent Bell Labs. The other options in this section
1209# have no effect if this option is set to NO (the default)
1210
1211HAVE_DOT = NO 263HAVE_DOT = NO
1212 264DOT_NUM_THREADS = 0
1213# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 265DOT_FONTNAME = Helvetica
1214# will generate a graph for each documented class showing the direct and 266DOT_FONTSIZE = 10
1215# indirect inheritance relations. Setting this tag to YES will force the 267DOT_FONTPATH =
1216# the CLASS_DIAGRAMS tag to NO.
1217
1218CLASS_GRAPH = YES 268CLASS_GRAPH = YES
1219
1220# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
1221# will generate a graph for each documented class showing the direct and
1222# indirect implementation dependencies (inheritance, containment, and
1223# class references variables) of the class with other documented classes.
1224
1225COLLABORATION_GRAPH = YES 269COLLABORATION_GRAPH = YES
1226
1227# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
1228# will generate a graph for groups, showing the direct groups dependencies
1229
1230GROUP_GRAPHS = YES 270GROUP_GRAPHS = YES
1231
1232# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
1233# collaboration diagrams in a style similar to the OMG's Unified Modeling
1234# Language.
1235
1236UML_LOOK = NO 271UML_LOOK = NO
1237 272UML_LIMIT_NUM_FIELDS = 10
1238# If set to YES, the inheritance and collaboration graphs will show the
1239# relations between templates and their instances.
1240
1241TEMPLATE_RELATIONS = NO 273TEMPLATE_RELATIONS = NO
1242
1243# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
1244# tags are set to YES then doxygen will generate a graph for each documented
1245# file showing the direct and indirect include dependencies of the file with
1246# other documented files.
1247
1248INCLUDE_GRAPH = YES 274INCLUDE_GRAPH = YES
1249
1250# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
1251# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
1252# documented header file showing the documented files that directly or
1253# indirectly include this file.
1254
1255INCLUDED_BY_GRAPH = YES 275INCLUDED_BY_GRAPH = YES
1256
1257# If the CALL_GRAPH and HAVE_DOT options are set to YES then
1258# doxygen will generate a call dependency graph for every global function
1259# or class method. Note that enabling this option will significantly increase
1260# the time of a run. So in most cases it will be better to enable call graphs
1261# for selected functions only using the \callgraph command.
1262
1263CALL_GRAPH = NO 276CALL_GRAPH = NO
1264
1265# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
1266# doxygen will generate a caller dependency graph for every global function
1267# or class method. Note that enabling this option will significantly increase
1268# the time of a run. So in most cases it will be better to enable caller
1269# graphs for selected functions only using the \callergraph command.
1270
1271CALLER_GRAPH = NO 277CALLER_GRAPH = NO
1272
1273# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
1274# will graphical hierarchy of all classes instead of a textual one.
1275
1276GRAPHICAL_HIERARCHY = YES 278GRAPHICAL_HIERARCHY = YES
1277
1278# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
1279# then doxygen will show the dependencies a directory has on other directories
1280# in a graphical way. The dependency relations are determined by the #include
1281# relations between the files in the directories.
1282
1283DIRECTORY_GRAPH = YES 279DIRECTORY_GRAPH = YES
1284
1285# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
1286# generated by dot. Possible values are png, jpg, or gif
1287# If left blank png will be used.
1288
1289DOT_IMAGE_FORMAT = png 280DOT_IMAGE_FORMAT = png
1290 281INTERACTIVE_SVG = NO
1291# The tag DOT_PATH can be used to specify the path where the dot tool can be 282DOT_PATH =
1292# found. If left blank, it is assumed the dot tool can be found in the path. 283DOTFILE_DIRS =
1293 284MSCFILE_DIRS =
1294DOT_PATH =
1295
1296# The DOTFILE_DIRS tag can be used to specify one or more directories that
1297# contain dot files that are included in the documentation (see the
1298# \dotfile command).
1299
1300DOTFILE_DIRS =
1301
1302# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
1303# nodes that will be shown in the graph. If the number of nodes in a graph
1304# becomes larger than this value, doxygen will truncate the graph, which is
1305# visualized by representing a node as a red box. Note that doxygen if the
1306# number of direct children of the root node in a graph is already larger than
1307# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
1308# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
1309
1310DOT_GRAPH_MAX_NODES = 50 285DOT_GRAPH_MAX_NODES = 50
1311
1312# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
1313# graphs generated by dot. A depth value of 3 means that only nodes reachable
1314# from the root by following a path via at most 3 edges will be shown. Nodes
1315# that lay further from the root node will be omitted. Note that setting this
1316# option to 1 or 2 may greatly reduce the computation time needed for large
1317# code bases. Also note that the size of a graph can be further restricted by
1318# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
1319
1320MAX_DOT_GRAPH_DEPTH = 0 286MAX_DOT_GRAPH_DEPTH = 0
1321
1322# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
1323# background. This is enabled by default, which results in a transparent
1324# background. Warning: Depending on the platform used, enabling this option
1325# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
1326# become hard to read).
1327
1328DOT_TRANSPARENT = YES 287DOT_TRANSPARENT = YES
1329
1330# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
1331# files in one run (i.e. multiple -o and -T options on the command line). This
1332# makes dot run faster, but since only newer versions of dot (>1.8.10)
1333# support this, this feature is disabled by default.
1334
1335DOT_MULTI_TARGETS = NO 288DOT_MULTI_TARGETS = NO
1336
1337# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
1338# generate a legend page explaining the meaning of the various boxes and
1339# arrows in the dot generated graphs.
1340
1341GENERATE_LEGEND = YES 289GENERATE_LEGEND = YES
1342
1343# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
1344# remove the intermediate dot files that are used to generate
1345# the various graphs.
1346
1347DOT_CLEANUP = YES 290DOT_CLEANUP = YES
1348
1349#---------------------------------------------------------------------------
1350# Configuration::additions related to the search engine
1351#---------------------------------------------------------------------------
1352
1353# The SEARCHENGINE tag specifies whether or not a search engine should be
1354# used. If set to NO the values of all tags below this one will be ignored.
1355
1356SEARCHENGINE = YES
diff --git a/prebuild.xml b/prebuild.xml
index fba7b27..2bee760 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -105,6 +105,7 @@
105 <Reference name="Nini" path="../../bin/"/> 105 <Reference name="Nini" path="../../bin/"/>
106 <Reference name="log4net" path="../../bin/"/> 106 <Reference name="log4net" path="../../bin/"/>
107 <Reference name="Mono.Addins" path="../../bin/"/> 107 <Reference name="Mono.Addins" path="../../bin/"/>
108 <Reference name="Mono.Addins.Setup" path="../../bin/"/>
108 <Reference name="SmartThreadPool"/> 109 <Reference name="SmartThreadPool"/>
109 <Files> 110 <Files>
110 <Match pattern="*.cs" recurse="false"/> 111 <Match pattern="*.cs" recurse="false"/>
@@ -851,10 +852,14 @@
851 852
852 <ReferencePath>../../../bin/</ReferencePath> 853 <ReferencePath>../../../bin/</ReferencePath>
853 <Reference name="System"/> 854 <Reference name="System"/>
855 <Reference name="System.Core"/>
854 <Reference name="System.Xml"/> 856 <Reference name="System.Xml"/>
855 <Reference name="System.Web"/> 857 <Reference name="System.Web"/>
856 <Reference name="OpenMetaverseTypes" path="../../../bin/"/> 858 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
859 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
857 <Reference name="OpenMetaverse" path="../../../bin/"/> 860 <Reference name="OpenMetaverse" path="../../../bin/"/>
861 <Reference name="Mono.Addins" path="../../../bin/"/>
862 <Reference name="Mono.Addins.Setup" path="../../../bin/"/>
858 <Reference name="OpenSim.Framework"/> 863 <Reference name="OpenSim.Framework"/>
859 <Reference name="OpenSim.Framework.Console"/> 864 <Reference name="OpenSim.Framework.Console"/>
860 <Reference name="OpenSim.Framework.Servers"/> 865 <Reference name="OpenSim.Framework.Servers"/>
@@ -977,6 +982,7 @@
977 <Reference name="OpenMetaverseTypes" path="../../../bin/"/> 982 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
978 <Reference name="OpenMetaverse" path="../../../bin/"/> 983 <Reference name="OpenMetaverse" path="../../../bin/"/>
979 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/> 984 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
985 <Reference name="Mono.Addins" path="../../../bin/"/>
980 <Reference name="OpenSim.Data"/> 986 <Reference name="OpenSim.Data"/>
981 <Reference name="OpenSim.Framework"/> 987 <Reference name="OpenSim.Framework"/>
982 <Reference name="OpenSim.Framework.Communications"/> 988 <Reference name="OpenSim.Framework.Communications"/>
@@ -985,7 +991,6 @@
985 <Reference name="OpenSim.Server.Base"/> 991 <Reference name="OpenSim.Server.Base"/>
986 <Reference name="OpenSim.Services.Base"/> 992 <Reference name="OpenSim.Services.Base"/>
987 <Reference name="OpenSim.Services.Interfaces"/> 993 <Reference name="OpenSim.Services.Interfaces"/>
988 <Reference name="Mono.Addins" path="../../../bin/"/>
989 <Reference name="Nini" path="../../../bin/"/> 994 <Reference name="Nini" path="../../../bin/"/>
990 <Reference name="log4net" path="../../../bin/"/> 995 <Reference name="log4net" path="../../../bin/"/>
991 <Reference name="XMLRPC" path="../../../bin/"/> 996 <Reference name="XMLRPC" path="../../../bin/"/>
@@ -1384,6 +1389,7 @@
1384 <Reference name="Nini" path="../../../bin/"/> 1389 <Reference name="Nini" path="../../../bin/"/>
1385 <Reference name="log4net" path="../../../bin/"/> 1390 <Reference name="log4net" path="../../../bin/"/>
1386 <Reference name="DotNetOpenId" path="../../../bin/"/> 1391 <Reference name="DotNetOpenId" path="../../../bin/"/>
1392 <Reference name="Mono.Addins" path="../../../bin/"/>
1387 1393
1388 <Files> 1394 <Files>
1389 <Match pattern="*.cs" recurse="true"> 1395 <Match pattern="*.cs" recurse="true">
@@ -1460,6 +1466,8 @@
1460 <Reference name="OpenSim.Server.Handlers"/> 1466 <Reference name="OpenSim.Server.Handlers"/>
1461 <Reference name="Nini" path="../../bin/"/> 1467 <Reference name="Nini" path="../../bin/"/>
1462 <Reference name="log4net" path="../../bin/"/> 1468 <Reference name="log4net" path="../../bin/"/>
1469 <Reference name="Mono.Addins" path="../../bin/"/>
1470 <Reference name="Mono.Addins.Setup" path="../../bin/"/>
1463 1471
1464 <Files> 1472 <Files>
1465 <Match pattern="*.cs" recurse="false"> 1473 <Match pattern="*.cs" recurse="false">
@@ -1579,6 +1587,8 @@
1579 </Files> 1587 </Files>
1580 </Project> 1588 </Project>
1581 1589
1590
1591
1582 <Project frameworkVersion="v3_5" name="OpenSim.Region.ClientStack.LindenCaps" path="OpenSim/Region/ClientStack/Linden/Caps" type="Library"> 1592 <Project frameworkVersion="v3_5" name="OpenSim.Region.ClientStack.LindenCaps" path="OpenSim/Region/ClientStack/Linden/Caps" type="Library">
1583 <Configuration name="Debug"> 1593 <Configuration name="Debug">
1584 <Options> 1594 <Options>
@@ -1624,6 +1634,7 @@
1624 </Files> 1634 </Files>
1625 </Project> 1635 </Project>
1626 1636
1637
1627 <Project frameworkVersion="v3_5" name="OpenSim.Region.CoreModules" path="OpenSim/Region/CoreModules" type="Library"> 1638 <Project frameworkVersion="v3_5" name="OpenSim.Region.CoreModules" path="OpenSim/Region/CoreModules" type="Library">
1628 <Configuration name="Debug"> 1639 <Configuration name="Debug">
1629 <Options> 1640 <Options>
@@ -1801,6 +1812,7 @@
1801 1812
1802 <ReferencePath>../../../bin/</ReferencePath> 1813 <ReferencePath>../../../bin/</ReferencePath>
1803 <Reference name="System"/> 1814 <Reference name="System"/>
1815 <Reference name="System.Core"/>
1804 <Reference name="System.Xml"/> 1816 <Reference name="System.Xml"/>
1805 <Reference name="OpenSim.Data"/> 1817 <Reference name="OpenSim.Data"/>
1806 <Reference name="OpenMetaverseTypes" path="../../../bin/"/> 1818 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
@@ -1843,11 +1855,13 @@
1843 <Configuration name="Debug"> 1855 <Configuration name="Debug">
1844 <Options> 1856 <Options>
1845 <OutputPath>../../../../bin/Physics/</OutputPath> 1857 <OutputPath>../../../../bin/Physics/</OutputPath>
1858 <AllowUnsafe>true</AllowUnsafe>
1846 </Options> 1859 </Options>
1847 </Configuration> 1860 </Configuration>
1848 <Configuration name="Release"> 1861 <Configuration name="Release">
1849 <Options> 1862 <Options>
1850 <OutputPath>../../../../bin/Physics/</OutputPath> 1863 <OutputPath>../../../../bin/Physics/</OutputPath>
1864 <AllowUnsafe>true</AllowUnsafe>
1851 </Options> 1865 </Options>
1852 </Configuration> 1866 </Configuration>
1853 1867
@@ -1863,6 +1877,7 @@
1863 <Reference name="OpenSim.Framework.Console"/> 1877 <Reference name="OpenSim.Framework.Console"/>
1864 <Reference name="OpenSim.Region.Physics.Manager"/> 1878 <Reference name="OpenSim.Region.Physics.Manager"/>
1865 <Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/> 1879 <Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/>
1880 <Reference name="BulletXNA.dll" path="../../../../bin/"/>
1866 <Reference name="log4net.dll" path="../../../../bin/"/> 1881 <Reference name="log4net.dll" path="../../../../bin/"/>
1867 1882
1868 <Files> 1883 <Files>
@@ -2169,7 +2184,7 @@
2169 <Reference name="OpenMetaverseTypes" path="../../../bin/"/> 2184 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
2170 <Reference name="OpenMetaverse" path="../../../bin/"/> 2185 <Reference name="OpenMetaverse" path="../../../bin/"/>
2171 <Reference name="Nini" path="../../../bin/"/> 2186 <Reference name="Nini" path="../../../bin/"/>
2172 <Reference name="Mono.Addins"/> 2187 <Reference name="Mono.Addins" path="../../../bin/"/>
2173 <Reference name="log4net" path="../../../bin/"/> 2188 <Reference name="log4net" path="../../../bin/"/>
2174 <Files> 2189 <Files>
2175 <Match pattern="*.cs" recurse="true"/> 2190 <Match pattern="*.cs" recurse="true"/>
@@ -2499,6 +2514,42 @@
2499 <Reference name="log4net" path="../../../../../bin/"/> 2514 <Reference name="log4net" path="../../../../../bin/"/>
2500 2515
2501 <Files> 2516 <Files>
2517 <Match pattern="*.cs" recurse="true">
2518 <Exclude name="Tests" pattern="Tests"/>
2519 </Match>
2520 </Files>
2521 </Project>
2522
2523 <Project frameworkVersion="v3_5" name="OpenSim.Region.ScriptEngine.XEngine.Api.Runtime" path="OpenSim/Region/ScriptEngine/XEngine/Api/Runtime" type="Library">
2524 <Configuration name="Debug">
2525 <Options>
2526 <OutputPath>../../../../../../bin/</OutputPath>
2527 </Options>
2528 </Configuration>
2529 <Configuration name="Release">
2530 <Options>
2531 <OutputPath>../../../../../../bin/</OutputPath>
2532 </Options>
2533 </Configuration>
2534
2535 <ReferencePath>../../../../../../bin/</ReferencePath>
2536 <Reference name="System"/>
2537 <Reference name="System.Data"/>
2538 <Reference name="System.Web"/>
2539 <Reference name="System.Xml"/>
2540 <Reference name="OpenMetaverseTypes" path="../../../../../../bin/"/>
2541 <Reference name="OpenSim"/>
2542 <Reference name="OpenSim.Framework"/>
2543 <Reference name="OpenSim.Framework.Communications"/>
2544 <Reference name="OpenSim.Region.Framework"/>
2545 <Reference name="OpenSim.Region.CoreModules"/>
2546 <Reference name="OpenSim.Framework.Console"/>
2547 <Reference name="OpenSim.Region.ScriptEngine.Shared"/>
2548 <Reference name="OpenSim.Region.ScriptEngine.Shared.Api.Runtime"/>
2549 <Reference name="Nini" path="../../../../../../bin/"/>
2550 <Reference name="log4net" path="../../../../../../bin/"/>
2551
2552 <Files>
2502 <Match pattern="*.cs" recurse="true"/> 2553 <Match pattern="*.cs" recurse="true"/>
2503 </Files> 2554 </Files>
2504 </Project> 2555 </Project>
@@ -2533,6 +2584,8 @@
2533 <Reference name="OpenSim.Region.ScriptEngine.Shared.CodeTools"/> 2584 <Reference name="OpenSim.Region.ScriptEngine.Shared.CodeTools"/>
2534 <Reference name="OpenSim.Region.ScriptEngine.Shared.Instance"/> 2585 <Reference name="OpenSim.Region.ScriptEngine.Shared.Instance"/>
2535 <Reference name="OpenSim.Region.ScriptEngine.Shared.Api"/> 2586 <Reference name="OpenSim.Region.ScriptEngine.Shared.Api"/>
2587 <Reference name="OpenSim.Region.ScriptEngine.Shared.Api.Runtime"/>
2588 <Reference name="OpenSim.Region.ScriptEngine.XEngine.Api.Runtime"/>
2536 <Reference name="SmartThreadPool"/> 2589 <Reference name="SmartThreadPool"/>
2537 <Reference name="Nini" path="../../../../bin/"/> 2590 <Reference name="Nini" path="../../../../bin/"/>
2538 <Reference name="log4net" path="../../../../bin/"/> 2591 <Reference name="log4net" path="../../../../bin/"/>
@@ -2540,6 +2593,7 @@
2540 <Files> 2593 <Files>
2541 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/> 2594 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
2542 <Match pattern="*.cs" recurse="true"> 2595 <Match pattern="*.cs" recurse="true">
2596 <Exclude name="Api"/>
2543 <Exclude name="Tests" pattern="Tests"/> 2597 <Exclude name="Tests" pattern="Tests"/>
2544 </Match> 2598 </Match>
2545 </Files> 2599 </Files>
@@ -2578,7 +2632,7 @@
2578 <Reference name="OpenSim.Framework.Servers.HttpServer"/> 2632 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
2579 <Reference name="OpenSim.Region.Physics.Manager"/> 2633 <Reference name="OpenSim.Region.Physics.Manager"/>
2580 <Reference name="Mono.Data.SqliteClient" path="../../../bin/"/> 2634 <Reference name="Mono.Data.SqliteClient" path="../../../bin/"/>
2581 <Reference name="Mono.Addins"/> 2635 <Reference name="Mono.Addins" path="../../../bin/"/>
2582 2636
2583 <!-- For scripting in funny languages by default --> 2637 <!-- For scripting in funny languages by default -->
2584 <Reference name="XMLRPC" path="../../../bin/"/> 2638 <Reference name="XMLRPC" path="../../../bin/"/>
@@ -2809,18 +2863,20 @@
2809 <Reference name="nunit.framework" path="../../../bin/"/> 2863 <Reference name="nunit.framework" path="../../../bin/"/>
2810 <Reference name="OpenMetaverse" path="../../../bin/"/> 2864 <Reference name="OpenMetaverse" path="../../../bin/"/>
2811 <Reference name="OpenMetaverseTypes" path="../../../bin/"/> 2865 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
2866 <Reference name="OpenSim.Data"/>
2867 <Reference name="OpenSim.Data.Null"/>
2812 <Reference name="OpenSim.Framework"/> 2868 <Reference name="OpenSim.Framework"/>
2813 <Reference name="OpenSim.Framework.Communications"/> 2869 <Reference name="OpenSim.Framework.Communications"/>
2814 <Reference name="OpenSim.Framework.Console"/> 2870 <Reference name="OpenSim.Framework.Console"/>
2815 <Reference name="OpenSim.Framework.Servers"/> 2871 <Reference name="OpenSim.Framework.Servers"/>
2816 <Reference name="OpenSim.Framework.Servers.HttpServer"/> 2872 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
2817 <Reference name="OpenSim.Data"/>
2818 <Reference name="OpenSim.Services.Interfaces"/>
2819 <Reference name="OpenSim.Server.Base"/>
2820 <Reference name="OpenSim.Region.Framework"/> 2873 <Reference name="OpenSim.Region.Framework"/>
2821 <Reference name="OpenSim.Region.CoreModules"/> 2874 <Reference name="OpenSim.Region.CoreModules"/>
2822 <Reference name="OpenSim.Region.OptionalModules"/> 2875 <Reference name="OpenSim.Region.OptionalModules"/>
2823 <Reference name="OpenSim.Region.Physics.Manager"/> 2876 <Reference name="OpenSim.Region.Physics.Manager"/>
2877 <Reference name="OpenSim.Region.ScriptEngine.Shared"/>
2878 <Reference name="OpenSim.Server.Base"/>
2879 <Reference name="OpenSim.Services.Interfaces"/>
2824 2880
2825 <Files> 2881 <Files>
2826 <Match pattern="*.cs" recurse="true"/> 2882 <Match pattern="*.cs" recurse="true"/>
@@ -2840,10 +2896,11 @@
2840 </Configuration> 2896 </Configuration>
2841 2897
2842 <ReferencePath>../../bin/</ReferencePath> 2898 <ReferencePath>../../bin/</ReferencePath>
2843 <Reference name="OpenSim.Framework"/>
2844 <Reference name="Nini" path="../../bin/"/> 2899 <Reference name="Nini" path="../../bin/"/>
2845 <Reference name="nunit.framework" path="../../bin/"/> 2900 <Reference name="nunit.framework" path="../../bin/"/>
2846 <Reference name="OpenSim"/> 2901 <Reference name="OpenSim"/>
2902 <Reference name="OpenSim.Framework"/>
2903 <Reference name="OpenSim.Tests.Common"/>
2847 <Files> 2904 <Files>
2848 <Match pattern="*.cs" recurse="false"/> 2905 <Match pattern="*.cs" recurse="false"/>
2849 </Files> 2906 </Files>
@@ -3095,6 +3152,7 @@
3095 <Reference name="System.Drawing"/> 3152 <Reference name="System.Drawing"/>
3096 <Reference name="OpenMetaverseTypes" path="../../../bin/"/> 3153 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
3097 <Reference name="OpenMetaverse" path="../../../bin/"/> 3154 <Reference name="OpenMetaverse" path="../../../bin/"/>
3155 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
3098 <Reference name="OpenSim.Data"/> 3156 <Reference name="OpenSim.Data"/>
3099 <Reference name="OpenSim.Data.Null"/> 3157 <Reference name="OpenSim.Data.Null"/>
3100 <Reference name="OpenSim.Framework"/> 3158 <Reference name="OpenSim.Framework"/>
@@ -3106,6 +3164,7 @@
3106 <Reference name="OpenSim.Framework.Servers.HttpServer"/> 3164 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
3107 <Reference name="OpenSim.Region.Framework"/> 3165 <Reference name="OpenSim.Region.Framework"/>
3108 <Reference name="OpenSim.Region.CoreModules"/> 3166 <Reference name="OpenSim.Region.CoreModules"/>
3167 <Reference name="OpenSim.Region.OptionalModules"/>
3109 <Reference name="OpenSim.Region.Physics.Manager"/> 3168 <Reference name="OpenSim.Region.Physics.Manager"/>
3110 <Reference name="OpenSim.Region.ScriptEngine.Shared"/> 3169 <Reference name="OpenSim.Region.ScriptEngine.Shared"/>
3111 <Reference name="OpenSim.Region.ScriptEngine.XEngine"/> 3170 <Reference name="OpenSim.Region.ScriptEngine.XEngine"/>
@@ -3181,6 +3240,7 @@
3181 <Reference name="OpenSim.Region.CoreModules"/> 3240 <Reference name="OpenSim.Region.CoreModules"/>
3182 <Reference name="OpenSim.Region.OptionalModules"/> 3241 <Reference name="OpenSim.Region.OptionalModules"/>
3183 <Reference name="OpenSim.Region.Physics.Manager"/> 3242 <Reference name="OpenSim.Region.Physics.Manager"/>
3243 <Reference name="OpenSim.Region.ScriptEngine.Shared"/>
3184 <Reference name="OpenSim.Services.AvatarService"/> 3244 <Reference name="OpenSim.Services.AvatarService"/>
3185 <Reference name="OpenSim.Services.Interfaces"/> 3245 <Reference name="OpenSim.Services.Interfaces"/>
3186 3246
@@ -3205,6 +3265,7 @@
3205 <Files> 3265 <Files>
3206 <!-- SADLY the way this works means you need to keep adding these paths --> 3266 <!-- SADLY the way this works means you need to keep adding these paths -->
3207 <Match path="Avatar/XmlRpcGroups/Tests" pattern="*.cs" recurse="true"/> 3267 <Match path="Avatar/XmlRpcGroups/Tests" pattern="*.cs" recurse="true"/>
3268 <Match path="Scripting/JsonStore/Tests" pattern="*.cs" recurse="true"/>
3208 <Match path="World/NPC/Tests" pattern="*.cs" recurse="true"/> 3269 <Match path="World/NPC/Tests" pattern="*.cs" recurse="true"/>
3209 </Files> 3270 </Files>
3210 </Project> 3271 </Project>
@@ -3364,6 +3425,7 @@
3364 <Reference name="OpenSim.Region.ScriptEngine.Shared"/> 3425 <Reference name="OpenSim.Region.ScriptEngine.Shared"/>
3365 <Reference name="OpenSim.Region.ScriptEngine.Shared.Api"/> 3426 <Reference name="OpenSim.Region.ScriptEngine.Shared.Api"/>
3366 <Reference name="OpenSim.Region.ScriptEngine.Shared.Api.Runtime"/> 3427 <Reference name="OpenSim.Region.ScriptEngine.Shared.Api.Runtime"/>
3428 <Reference name="OpenSim.Region.ScriptEngine.Shared.Instance"/>
3367 <Reference name="OpenSim.Region.ScriptEngine.XEngine"/> 3429 <Reference name="OpenSim.Region.ScriptEngine.XEngine"/>
3368 <Reference name="OpenSim.Services.Interfaces"/> 3430 <Reference name="OpenSim.Services.Interfaces"/>
3369 <Reference name="OpenSim.Tests.Common"/> 3431 <Reference name="OpenSim.Tests.Common"/>
@@ -3387,6 +3449,7 @@
3387 <!-- SADLY the way this works means you need to keep adding these paths --> 3449 <!-- SADLY the way this works means you need to keep adding these paths -->
3388 <Match path="Shared/Tests" pattern="*.cs" recurse="true"/> 3450 <Match path="Shared/Tests" pattern="*.cs" recurse="true"/>
3389 <Match path="Shared/CodeTools/Tests" pattern="*.cs" recurse="true"/> 3451 <Match path="Shared/CodeTools/Tests" pattern="*.cs" recurse="true"/>
3452 <Match path="Shared/Instance/Tests" pattern="*.cs" recurse="true"/>
3390 <Match path="XEngine/Tests" pattern="*.cs" recurse="true"/> 3453 <Match path="XEngine/Tests" pattern="*.cs" recurse="true"/>
3391 </Files> 3454 </Files>
3392 </Project> 3455 </Project>
@@ -3416,6 +3479,7 @@
3416 <Reference name="OpenSim.Framework.Console"/> 3479 <Reference name="OpenSim.Framework.Console"/>
3417 <Reference name="OpenSim.Region.Physics.Manager"/> 3480 <Reference name="OpenSim.Region.Physics.Manager"/>
3418 <Reference name="OpenSim.Region.Physics.OdePlugin" path="../../../../../bin/Physics/"/> 3481 <Reference name="OpenSim.Region.Physics.OdePlugin" path="../../../../../bin/Physics/"/>
3482 <Reference name="OpenSim.Tests.Common"/>
3419 <Reference name="Ode.NET" path="../../../../../bin/"/> 3483 <Reference name="Ode.NET" path="../../../../../bin/"/>
3420 <Reference name="nunit.framework" path="../../../../../bin/"/> 3484 <Reference name="nunit.framework" path="../../../../../bin/"/>
3421 <Reference name="log4net" path="../../../../../bin/"/> 3485 <Reference name="log4net" path="../../../../../bin/"/>
@@ -3425,6 +3489,40 @@
3425 </Files> 3489 </Files>
3426 </Project> 3490 </Project>
3427 3491
3492 <Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.BulletSPlugin.Tests" path="OpenSim/Region/Physics/BulletSPlugin/Tests" type="Library">
3493 <Configuration name="Debug">
3494 <Options>
3495 <OutputPath>../../../../../bin/</OutputPath>
3496 </Options>
3497 </Configuration>
3498 <Configuration name="Release">
3499 <Options>
3500 <OutputPath>../../../../../bin/</OutputPath>
3501 </Options>
3502 </Configuration>
3503
3504 <ReferencePath>../../../../../bin/</ReferencePath>
3505 <Reference name="System"/>
3506 <Reference name="System.Core"/>
3507 <Reference name="System.Data"/>
3508 <Reference name="Nini" path="../../../../../bin/"/>
3509 <Reference name="log4net" path="../../../../../bin/"/>
3510 <Reference name="nunit.framework" path="../../../../../bin/"/>
3511 <Reference name="OpenMetaverse" path="../../../../../bin/"/>
3512 <Reference name="OpenMetaverseTypes" path="../../../../../bin/"/>
3513 <Reference name="OpenSim.Framework"/>
3514 <Reference name="OpenSim.Tests.Common"/>
3515 <Reference name="OpenSim.Region.CoreModules"/>
3516 <Reference name="OpenSim.Region.Physics.Meshing" path="../../../../../bin/Physics/"/>
3517 <Reference name="OpenSim.Region.Physics.Manager"/>
3518 <Reference name="OpenSim.Region.Physics.BulletSPlugin" path="../../../../../bin/Physics/"/>
3519
3520 <Files>
3521 <Match pattern="*.cs" recurse="false"/>
3522 </Files>
3523 </Project>
3524
3525
3428 <Project frameworkVersion="v3_5" name="OpenSim.Server.Handlers.Tests" path="OpenSim/Server/Handlers" type="Library"> 3526 <Project frameworkVersion="v3_5" name="OpenSim.Server.Handlers.Tests" path="OpenSim/Server/Handlers" type="Library">
3429 <Configuration name="Debug"> 3527 <Configuration name="Debug">
3430 <Options> 3528 <Options>
diff --git a/share/Schemas/SceneObjectPart0.xsd b/share/Schemas/SceneObjectPart0.xsd
deleted file mode 100644
index 0da7618..0000000
--- a/share/Schemas/SceneObjectPart0.xsd
+++ /dev/null
@@ -1,166 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
2<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
3 <xs:import namespace="http://microsoft.com/wsdl/types/" />
4 <xs:import namespace="http://www.w3.org/2001/XMLSchema" />
5 <xs:element name="SceneObjectPart" nillable="true" type="SceneObjectPart" />
6 <xs:complexType name="SceneObjectPart">
7 <xs:sequence>
8 <xs:element minOccurs="1" maxOccurs="1" name="LastOwnerID" type="LLUUID" />
9 <xs:element minOccurs="1" maxOccurs="1" name="OwnerID" type="LLUUID" />
10 <xs:element minOccurs="1" maxOccurs="1" name="GroupID" type="LLUUID" />
11 <xs:element minOccurs="1" maxOccurs="1" name="OwnershipCost" type="xs:int" />
12 <xs:element minOccurs="1" maxOccurs="1" name="ObjectSaleType" type="xs:unsignedByte" />
13 <xs:element minOccurs="1" maxOccurs="1" name="SalePrice" type="xs:int" />
14 <xs:element minOccurs="1" maxOccurs="1" name="Category" type="xs:unsignedInt" />
15 <xs:element minOccurs="1" maxOccurs="1" name="CreationDate" type="xs:int" />
16 <xs:element minOccurs="1" maxOccurs="1" name="ParentID" type="xs:unsignedInt" />
17 <xs:element minOccurs="1" maxOccurs="1" name="m_sitTargetAvatar" type="LLUUID" />
18 <xs:element minOccurs="1" maxOccurs="1" name="BaseMask" type="xs:unsignedInt" />
19 <xs:element minOccurs="1" maxOccurs="1" name="OwnerMask" type="xs:unsignedInt" />
20 <xs:element minOccurs="1" maxOccurs="1" name="GroupMask" type="xs:unsignedInt" />
21 <xs:element minOccurs="1" maxOccurs="1" name="EveryoneMask" type="xs:unsignedInt" />
22 <xs:element minOccurs="1" maxOccurs="1" name="NextOwnerMask" type="xs:unsignedInt" />
23 <xs:element minOccurs="1" maxOccurs="1" name="Flags" type="ObjectFlags" />
24 <xs:element minOccurs="1" maxOccurs="1" name="CreatorID" type="LLUUID" />
25 <xs:element minOccurs="1" maxOccurs="1" name="FolderID" type="LLUUID" />
26 <xs:element minOccurs="1" maxOccurs="1" name="InventorySerial" type="xs:unsignedInt" />
27 <xs:element minOccurs="0" maxOccurs="1" name="TaskInventory">
28 <xs:complexType>
29 <xs:sequence>
30 <xs:element ref="xs:schema" />
31 <xs:any />
32 </xs:sequence>
33 </xs:complexType>
34 </xs:element>
35 <xs:element minOccurs="1" maxOccurs="1" name="ObjectFlags" type="xs:unsignedInt" />
36 <xs:element minOccurs="1" maxOccurs="1" name="UUID" type="LLUUID" />
37 <xs:element minOccurs="1" maxOccurs="1" name="LocalId" type="xs:unsignedInt" />
38 <xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
39 <xs:element minOccurs="1" maxOccurs="1" name="Material" type="xs:unsignedByte" />
40 <xs:element minOccurs="1" maxOccurs="1" name="RegionHandle" type="xs:unsignedLong" />
41 <xs:element minOccurs="1" maxOccurs="1" name="ScriptAccessPin" type="xs:int" />
42 <xs:element minOccurs="1" maxOccurs="1" name="GroupPosition" type="LLVector3" />
43 <xs:element minOccurs="1" maxOccurs="1" name="OffsetPosition" type="LLVector3" />
44 <xs:element minOccurs="1" maxOccurs="1" name="RotationOffset" type="LLQuaternion" />
45 <xs:element minOccurs="1" maxOccurs="1" name="Velocity" type="LLVector3" />
46 <xs:element minOccurs="1" maxOccurs="1" name="RotationalVelocity" type="LLVector3" />
47 <xs:element minOccurs="1" maxOccurs="1" name="AngularVelocity" type="LLVector3" />
48 <xs:element minOccurs="1" maxOccurs="1" name="Acceleration" type="LLVector3" />
49 <xs:element minOccurs="0" maxOccurs="1" name="Description" type="xs:string" />
50 <xs:element minOccurs="1" maxOccurs="1" name="Color" type="Color" />
51 <xs:element minOccurs="0" maxOccurs="1" name="Text" type="xs:string" />
52 <xs:element minOccurs="0" maxOccurs="1" name="SitName" type="xs:string" />
53 <xs:element minOccurs="0" maxOccurs="1" name="TouchName" type="xs:string" />
54 <xs:element minOccurs="1" maxOccurs="1" name="LinkNum" type="xs:int" />
55 <xs:element minOccurs="1" maxOccurs="1" name="ClickAction" type="xs:unsignedByte" />
56 <xs:element minOccurs="0" maxOccurs="1" name="Shape" type="PrimitiveBaseShape" />
57 <xs:element minOccurs="1" maxOccurs="1" name="Scale" type="LLVector3" />
58 <xs:element minOccurs="1" maxOccurs="1" name="UpdateFlag" type="xs:unsignedByte" />
59 </xs:sequence>
60 </xs:complexType>
61 <xs:complexType name="LLUUID">
62 <xs:sequence>
63 <xs:element minOccurs="1" maxOccurs="1" name="UUID" xmlns:q1="http://microsoft.com/wsdl/types/" type="q1:guid" />
64 </xs:sequence>
65 </xs:complexType>
66 <xs:simpleType name="ObjectFlags">
67 <xs:list>
68 <xs:simpleType>
69 <xs:restriction base="xs:string">
70 <xs:enumeration value="None" />
71 <xs:enumeration value="Physics" />
72 <xs:enumeration value="CreateSelected" />
73 <xs:enumeration value="ObjectModify" />
74 <xs:enumeration value="ObjectCopy" />
75 <xs:enumeration value="ObjectAnyOwner" />
76 <xs:enumeration value="ObjectYouOwner" />
77 <xs:enumeration value="Scripted" />
78 <xs:enumeration value="Touch" />
79 <xs:enumeration value="ObjectMove" />
80 <xs:enumeration value="Money" />
81 <xs:enumeration value="Phantom" />
82 <xs:enumeration value="InventoryEmpty" />
83 <xs:enumeration value="JointHinge" />
84 <xs:enumeration value="JointP2P" />
85 <xs:enumeration value="JointLP2P" />
86 <xs:enumeration value="JointWheel" />
87 <xs:enumeration value="AllowInventoryDrop" />
88 <xs:enumeration value="ObjectTransfer" />
89 <xs:enumeration value="ObjectGroupOwned" />
90 <xs:enumeration value="ObjectYouOfficer" />
91 <xs:enumeration value="CameraDecoupled" />
92 <xs:enumeration value="AnimSource" />
93 <xs:enumeration value="CameraSource" />
94 <xs:enumeration value="CastShadows" />
95 <xs:enumeration value="ObjectOwnerModify" />
96 <xs:enumeration value="TemporaryOnRez" />
97 <xs:enumeration value="Temporary" />
98 <xs:enumeration value="ZlibCompressed" />
99 </xs:restriction>
100 </xs:simpleType>
101 </xs:list>
102 </xs:simpleType>
103 <xs:complexType name="LLVector3">
104 <xs:sequence>
105 <xs:element minOccurs="1" maxOccurs="1" name="X" type="xs:float" />
106 <xs:element minOccurs="1" maxOccurs="1" name="Y" type="xs:float" />
107 <xs:element minOccurs="1" maxOccurs="1" name="Z" type="xs:float" />
108 </xs:sequence>
109 </xs:complexType>
110 <xs:complexType name="LLQuaternion">
111 <xs:sequence>
112 <xs:element minOccurs="1" maxOccurs="1" name="X" type="xs:float" />
113 <xs:element minOccurs="1" maxOccurs="1" name="Y" type="xs:float" />
114 <xs:element minOccurs="1" maxOccurs="1" name="Z" type="xs:float" />
115 <xs:element minOccurs="1" maxOccurs="1" name="W" type="xs:float" />
116 </xs:sequence>
117 </xs:complexType>
118 <xs:complexType name="Color" />
119 <xs:complexType name="PrimitiveBaseShape">
120 <xs:sequence>
121 <xs:element minOccurs="1" maxOccurs="1" name="PathBegin" type="xs:unsignedShort" />
122 <xs:element minOccurs="1" maxOccurs="1" name="PathCurve" type="xs:unsignedByte" />
123 <xs:element minOccurs="1" maxOccurs="1" name="PathEnd" type="xs:unsignedShort" />
124 <xs:element minOccurs="1" maxOccurs="1" name="PathRadiusOffset" type="xs:byte" />
125 <xs:element minOccurs="1" maxOccurs="1" name="PathRevolutions" type="xs:unsignedByte" />
126 <xs:element minOccurs="1" maxOccurs="1" name="PathScaleX" type="xs:unsignedByte" />
127 <xs:element minOccurs="1" maxOccurs="1" name="PathScaleY" type="xs:unsignedByte" />
128 <xs:element minOccurs="1" maxOccurs="1" name="PathShearX" type="xs:unsignedByte" />
129 <xs:element minOccurs="1" maxOccurs="1" name="PathShearY" type="xs:unsignedByte" />
130 <xs:element minOccurs="1" maxOccurs="1" name="PathSkew" type="xs:byte" />
131 <xs:element minOccurs="1" maxOccurs="1" name="PathTaperX" type="xs:byte" />
132 <xs:element minOccurs="1" maxOccurs="1" name="PathTaperY" type="xs:byte" />
133 <xs:element
134 <xs:element minOccurs="1" maxOccurs="1" name="PathTwistBegin" type="xs:byte" />
135 <xs:element minOccurs="1" maxOccurs="1" name="PCode" type="xs:unsignedByte" />
136 <xs:element minOccurs="1" maxOccurs="1" name="ProfileBegin" type="xs:unsignedShort" />
137 <xs:element minOccurs="1" maxOccurs="1" name="ProfileEnd" type="xs:unsignedShort" />
138 <xs:element minOccurs="1" maxOccurs="1" name="ProfileHollow" type="xs:unsignedShort" />
139 <xs:element minOccurs="1" maxOccurs="1" name="Scale" type="LLVector3" />
140 <xs:element minOccurs="1" maxOccurs="1" name="State" type="xs:unsignedByte" />
141 <xs:element minOccurs="1" maxOccurs="1" name="ProfileShape" type="ProfileShape" />
142 <xs:element minOccurs="1" maxOccurs="1" name="HollowShape" type="HollowShape" />
143 <xs:element minOccurs="1" maxOccurs="1" name="ProfileCurve" type="xs:unsignedByte" />
144 <xs:element minOccurs="0" maxOccurs="1" name="TextureEntry" type="xs:base64Binary" />
145 <xs:element minOccurs="0" maxOccurs="1" name="ExtraParams" type="xs:base64Binary" />
146 </xs:sequence>
147 </xs:complexType>
148 <xs:simpleType name="ProfileShape">
149 <xs:restriction base="xs:string">
150 <xs:enumeration value="Circle" />
151 <xs:enumeration value="Square" />
152 <xs:enumeration value="IsometricTriangle" />
153 <xs:enumeration value="EquilateralTriangle" />
154 <xs:enumeration value="RightTriangle" />
155 <xs:enumeration value="HalfCircle" />
156 </xs:restriction>
157 </xs:simpleType>
158 <xs:simpleType name="HollowShape">
159 <xs:restriction base="xs:string">
160 <xs:enumeration value="Same" />
161 <xs:enumeration value="Circle" />
162 <xs:enumeration value="Square" />
163 <xs:enumeration value="Triangle" />
164 </xs:restriction>
165 </xs:simpleType>
166</xs:schema>
diff --git a/share/Schemas/SceneObjectPart1.xsd b/share/Schemas/SceneObjectPart1.xsd
deleted file mode 100644
index 2f38087..0000000
--- a/share/Schemas/SceneObjectPart1.xsd
+++ /dev/null
@@ -1,8 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
2<xs:schema xmlns:tns="http://microsoft.com/wsdl/types/" elementFormDefault="qualified" targetNamespace="http://microsoft.com/wsdl/types/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
3 <xs:simpleType name="guid">
4 <xs:restriction base="xs:string">
5 <xs:pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" />
6 </xs:restriction>
7 </xs:simpleType>
8</xs:schema>
diff --git a/share/php/generateUserFunction.php b/share/php/generateUserFunction.php
deleted file mode 100755
index a262bf5..0000000
--- a/share/php/generateUserFunction.php
+++ /dev/null
@@ -1,46 +0,0 @@
1<?php
2 // GenerateUser (v1.0)
3 // Creates a new user account, and returns it into an associative array.
4 // --
5 // $firstname - The users firstname
6 // $lastname - The users lastname
7 // $password - the users password
8 // $home - the regionhandle of the users home location
9 // --
10 function generateUser($firstname,$lastname,$password,$home) {
11 $user = array();
12 $user['UUID'] = sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
13 mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
14 mt_rand( 0, 0x0fff ) | 0x4000,
15 mt_rand( 0, 0x3fff ) | 0x8000,
16 mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ) );
17 $user['username'] = $firstname;
18 $user['lastname'] = $lastname;
19
20 $user['passwordSalt'] = md5(microtime() . mt_rand(0,0xffff));
21 $user['passwordHash'] = md5(md5($password) . ":" . $user['passwordSalt']);
22
23 $user['homeRegion'] = $home;
24 $user['homeLocationX'] = 128;
25 $user['homeLocationY'] = 128;
26 $user['homeLocationZ'] = 128;
27 $user['homeLookAtX'] = 15;
28 $user['homeLookAtY'] = 15;
29 $user['homeLookAtZ'] = 15;
30
31 $user['created'] = time();
32 $user['lastLogin'] = 0;
33
34 $user['userInventoryURI'] = "http://inventory.server.tld:8004/";
35 $user['userAssetURI'] = "http://asset.server.tld:8003/";
36
37 $user['profileCanDoMask'] = 0;
38 $user['profileWantDoMask'] = 0;
39 $user['profileAboutText'] = "I am a user.";
40 $user['profileFirstText'] = "Stuff.";
41 $user['profileImage'] = sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', 0, 0, 0, 0, 0, 0, 0, 0 );
42 $user['profileFirstImage'] = sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', 0, 0, 0, 0, 0, 0, 0, 0 );
43
44 return $user;
45 }
46?> \ No newline at end of file