aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/Application.cs42
-rw-r--r--OpenSim/Region/Application/ConfigurationLoader.cs76
-rw-r--r--OpenSim/Region/Application/OpenSim.cs297
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs92
-rw-r--r--OpenSim/Region/ClientStack/IClientNetworkServer.cs15
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs136
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs27
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs147
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs36
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs8
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs6
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs20
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs1
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs26
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs44
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs115
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs719
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs110
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs628
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs111
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs25
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs6
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs16
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs6
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs9
-rw-r--r--OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs6
-rw-r--r--OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs3
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs264
-rw-r--r--OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs129
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs129
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs65
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs23
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs16
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs12
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs24
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs36
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs12
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs111
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs449
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs1343
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs426
-rw-r--r--OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs353
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs42
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs19
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs69
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs211
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs197
-rw-r--r--OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs256
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs76
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs401
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs66
-rw-r--r--OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs9
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs198
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs21
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs226
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs46
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs49
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs20
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs5
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs7
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs66
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs3
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs26
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs79
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs73
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs33
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs61
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs218
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs256
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs298
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs227
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs27
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs538
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs27
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs44
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs9
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/WindModule.cs38
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs147
-rw-r--r--OpenSim/Region/DataSnapshot/DataRequestHandler.cs4
-rw-r--r--OpenSim/Region/DataSnapshot/DataSnapshotManager.cs2
-rw-r--r--OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/DataSnapshot/SnapshotStore.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs33
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs20
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.cs11
-rw-r--r--OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs48
-rw-r--r--OpenSim/Region/Framework/Interfaces/IGroupsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs119
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs19
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs8
-rw-r--r--OpenSim/Region/Framework/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs114
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs66
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs60
-rw-r--r--OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs185
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs823
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs34
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs49
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs192
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs738
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs113
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs86
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs111
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs90
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs175
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs71
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs119
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs167
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs13
-rw-r--r--OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs163
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs220
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs18
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs67
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs195
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs65
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs339
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs590
-rw-r--r--OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs2
-rwxr-xr-xOpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs432
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs195
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs41
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs41
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs10
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs38
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs26
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs18
-rw-r--r--OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs2
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs9
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs145
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs430
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs411
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs173
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs136
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs219
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs137
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs138
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActors.cs67
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs72
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs527
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs25
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs54
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs55
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs103
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs490
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs240
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs393
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs730
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs97
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs350
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs404
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs741
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs121
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs230
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs381
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs998
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs1163
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs33
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs82
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs56
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs51
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt131
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs34
-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/PhysicsActor.cs6
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs10
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs265
-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.cs1
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs2
-rw-r--r--OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs6
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs83
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs326
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs227
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs51
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs25
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs27
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs25
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSCodeTransformer.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/LSL_EventTests.cs359
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/lsl.parser.cs18172
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs35
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs85
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs399
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs238
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs24
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs6
-rw-r--r--OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs2
271 files changed, 31206 insertions, 15605 deletions
diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs
index c3e7ec2..3a4e5df 100644
--- a/OpenSim/Region/Application/Application.cs
+++ b/OpenSim/Region/Application/Application.cs
@@ -103,48 +103,63 @@ namespace OpenSim
103 "[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset"); 103 "[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
104 104
105 // Verify the Threadpool allocates or uses enough worker and IO completion threads 105 // Verify the Threadpool allocates or uses enough worker and IO completion threads
106 // .NET 2.0 workerthreads default to 50 * numcores 106 // .NET 2.0, workerthreads default to 50 * numcores
107 // .NET 3.0 workerthreads defaults to 250 * numcores 107 // .NET 3.0, workerthreads defaults to 250 * numcores
108 // .NET 4.0 workerthreads are dynamic based on bitness and OS resources 108 // .NET 4.0, workerthreads are dynamic based on bitness and OS resources
109 // Max IO Completion threads are 1000 on all 3 CLRs. 109 // Max IO Completion threads are 1000 on all 3 CLRs
110 //
111 // Mono 2.10.9 to at least Mono 3.1, workerthreads default to 100 * numcores, iocp threads to 4 * numcores
110 int workerThreadsMin = 500; 112 int workerThreadsMin = 500;
111 int workerThreadsMax = 1000; // may need further adjustment to match other CLR 113 int workerThreadsMax = 1000; // may need further adjustment to match other CLR
112 int iocpThreadsMin = 1000; 114 int iocpThreadsMin = 1000;
113 int iocpThreadsMax = 2000; // may need further adjustment to match other CLR 115 int iocpThreadsMax = 2000; // may need further adjustment to match other CLR
116
117 {
118 int currentMinWorkerThreads, currentMinIocpThreads;
119 System.Threading.ThreadPool.GetMinThreads(out currentMinWorkerThreads, out currentMinIocpThreads);
120 m_log.InfoFormat(
121 "[OPENSIM MAIN]: Runtime gave us {0} min worker threads and {1} min IOCP threads",
122 currentMinWorkerThreads, currentMinIocpThreads);
123 }
124
114 int workerThreads, iocpThreads; 125 int workerThreads, iocpThreads;
115 System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); 126 System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
116 m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} worker threads and {1} IOCP threads", workerThreads, iocpThreads); 127 m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} max worker threads and {1} max IOCP threads", workerThreads, iocpThreads);
128
117 if (workerThreads < workerThreadsMin) 129 if (workerThreads < workerThreadsMin)
118 { 130 {
119 workerThreads = workerThreadsMin; 131 workerThreads = workerThreadsMin;
120 m_log.InfoFormat("[OPENSIM MAIN]: Bumping up to worker threads to {0}",workerThreads); 132 m_log.InfoFormat("[OPENSIM MAIN]: Bumping up to max worker threads to {0}",workerThreads);
121 } 133 }
122 if (workerThreads > workerThreadsMax) 134 if (workerThreads > workerThreadsMax)
123 { 135 {
124 workerThreads = workerThreadsMax; 136 workerThreads = workerThreadsMax;
125 m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads); 137 m_log.InfoFormat("[OPENSIM MAIN]: Limiting max worker threads to {0}",workerThreads);
126 } 138 }
139
127 // Increase the number of IOCP threads available. 140 // Increase the number of IOCP threads available.
128 // Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17) 141 // Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17)
129 if (iocpThreads < iocpThreadsMin) 142 if (iocpThreads < iocpThreadsMin)
130 { 143 {
131 iocpThreads = iocpThreadsMin; 144 iocpThreads = iocpThreadsMin;
132 m_log.InfoFormat("[OPENSIM MAIN]: Bumping up IO completion threads to {0}",iocpThreads); 145 m_log.InfoFormat("[OPENSIM MAIN]: Bumping up max IOCP threads to {0}",iocpThreads);
133 } 146 }
134 // Make sure we don't overallocate IOCP threads and thrash system resources 147 // Make sure we don't overallocate IOCP threads and thrash system resources
135 if ( iocpThreads > iocpThreadsMax ) 148 if ( iocpThreads > iocpThreadsMax )
136 { 149 {
137 iocpThreads = iocpThreadsMax; 150 iocpThreads = iocpThreadsMax;
138 m_log.InfoFormat("[OPENSIM MAIN]: Limiting IO completion threads to {0}",iocpThreads); 151 m_log.InfoFormat("[OPENSIM MAIN]: Limiting max IOCP completion threads to {0}",iocpThreads);
139 } 152 }
140 // set the resulting worker and IO completion thread counts back to ThreadPool 153 // set the resulting worker and IO completion thread counts back to ThreadPool
141 if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) ) 154 if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) )
142 { 155 {
143 m_log.InfoFormat("[OPENSIM MAIN]: Threadpool set to {0} worker threads and {1} IO completion threads", workerThreads, iocpThreads); 156 m_log.InfoFormat(
157 "[OPENSIM MAIN]: Threadpool set to {0} max worker threads and {1} max IOCP threads",
158 workerThreads, iocpThreads);
144 } 159 }
145 else 160 else
146 { 161 {
147 m_log.Info("[OPENSIM MAIN]: Threadpool reconfiguration failed, runtime defaults still in effect."); 162 m_log.Warn("[OPENSIM MAIN]: Threadpool reconfiguration failed, runtime defaults still in effect.");
148 } 163 }
149 164
150 // Check if the system is compatible with OpenSimulator. 165 // Check if the system is compatible with OpenSimulator.
@@ -152,17 +167,16 @@ namespace OpenSim
152 string supported = String.Empty; 167 string supported = String.Empty;
153 if (Util.IsEnvironmentSupported(ref supported)) 168 if (Util.IsEnvironmentSupported(ref supported))
154 { 169 {
155 m_log.Info("Environment is compatible.\n"); 170 m_log.Info("[OPENSIM MAIN]: Environment is supported by OpenSimulator.");
156 } 171 }
157 else 172 else
158 { 173 {
159 m_log.Warn("Environment is unsupported (" + supported + ")\n"); 174 m_log.Warn("[OPENSIM MAIN]: Environment is not supported by OpenSimulator (" + supported + ")\n");
160 } 175 }
161 176
162 // Configure nIni aliases and localles 177 // Configure nIni aliases and localles
163 Culture.SetCurrentCulture(); 178 Culture.SetCurrentCulture();
164 179
165
166 // Validate that the user has the most basic configuration done 180 // Validate that the user has the most basic configuration done
167 // If not, offer to do the most basic configuration for them warning them along the way of the importance of 181 // If not, offer to do the most basic configuration for them warning them along the way of the importance of
168 // reading these files. 182 // reading these files.
diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs
index fc3999f..52e520c 100644
--- a/OpenSim/Region/Application/ConfigurationLoader.cs
+++ b/OpenSim/Region/Application/ConfigurationLoader.cs
@@ -124,7 +124,7 @@ namespace OpenSim
124 else 124 else
125 { 125 {
126 Application.iniFilePath = Path.GetFullPath( 126 Application.iniFilePath = Path.GetFullPath(
127 Path.Combine(Util.configDir(), iniFileName)); 127 Path.Combine(Util.configDir(), iniFileName));
128 128
129 if (!File.Exists(Application.iniFilePath)) 129 if (!File.Exists(Application.iniFilePath))
130 { 130 {
@@ -139,12 +139,29 @@ namespace OpenSim
139 } 139 }
140 } 140 }
141 141
142 m_config = new OpenSimConfigSource();
143 m_config.Source = new IniConfigSource();
144 m_config.Source.Merge(DefaultConfig());
145
146 m_log.Info("[CONFIG]: Reading configuration settings");
147
148 for (int i = 0 ; i < sources.Count ; i++)
149 {
150 if (ReadConfig(m_config, sources[i]))
151 {
152 iniFileExists = true;
153 AddIncludes(m_config, sources);
154 }
155 }
156
157 // Override distro settings with contents of inidirectory
142 string iniDirName = startupConfig.GetString("inidirectory", "config"); 158 string iniDirName = startupConfig.GetString("inidirectory", "config");
143 string iniDirPath = Path.Combine(Util.configDir(), iniDirName); 159 string iniDirPath = Path.Combine(Util.configDir(), iniDirName);
144 160
145 if (Directory.Exists(iniDirPath)) 161 if (Directory.Exists(iniDirPath))
146 { 162 {
147 m_log.InfoFormat("Searching folder {0} for config ini files", iniDirPath); 163 m_log.InfoFormat("[CONFIG]: Searching folder {0} for config ini files", iniDirPath);
164 List<string> overrideSources = new List<string>();
148 165
149 string[] fileEntries = Directory.GetFiles(iniDirName); 166 string[] fileEntries = Directory.GetFiles(iniDirName);
150 foreach (string filePath in fileEntries) 167 foreach (string filePath in fileEntries)
@@ -152,33 +169,38 @@ namespace OpenSim
152 if (Path.GetExtension(filePath).ToLower() == ".ini") 169 if (Path.GetExtension(filePath).ToLower() == ".ini")
153 { 170 {
154 if (!sources.Contains(Path.GetFullPath(filePath))) 171 if (!sources.Contains(Path.GetFullPath(filePath)))
172 {
173 overrideSources.Add(Path.GetFullPath(filePath));
174 // put it in sources too, to avoid circularity
155 sources.Add(Path.GetFullPath(filePath)); 175 sources.Add(Path.GetFullPath(filePath));
176 }
156 } 177 }
157 } 178 }
158 }
159 179
160 m_config = new OpenSimConfigSource();
161 m_config.Source = new IniConfigSource();
162 m_config.Source.Merge(DefaultConfig());
163 180
164 m_log.Info("[CONFIG]: Reading configuration settings"); 181 if (overrideSources.Count > 0)
182 {
183 OpenSimConfigSource overrideConfig = new OpenSimConfigSource();
184 overrideConfig.Source = new IniConfigSource();
185
186 for (int i = 0 ; i < overrideSources.Count ; i++)
187 {
188 if (ReadConfig(overrideConfig, overrideSources[i]))
189 {
190 iniFileExists = true;
191 AddIncludes(overrideConfig, overrideSources);
192 }
193 }
194 m_config.Source.Merge(overrideConfig.Source);
195 }
196 }
165 197
166 if (sources.Count == 0) 198 if (sources.Count == 0)
167 { 199 {
168 m_log.FatalFormat("[CONFIG]: Could not load any configuration"); 200 m_log.FatalFormat("[CONFIG]: Could not load any configuration");
169 Environment.Exit(1); 201 Environment.Exit(1);
170 } 202 }
171 203 else if (!iniFileExists)
172 for (int i = 0 ; i < sources.Count ; i++)
173 {
174 if (ReadConfig(sources[i]))
175 {
176 iniFileExists = true;
177 AddIncludes(sources);
178 }
179 }
180
181 if (!iniFileExists)
182 { 204 {
183 m_log.FatalFormat("[CONFIG]: Could not load any configuration"); 205 m_log.FatalFormat("[CONFIG]: Could not load any configuration");
184 m_log.FatalFormat("[CONFIG]: Configuration exists, but there was an error loading it!"); 206 m_log.FatalFormat("[CONFIG]: Configuration exists, but there was an error loading it!");
@@ -201,9 +223,9 @@ namespace OpenSim
201 223
202 envConfigSource.LoadEnv(); 224 envConfigSource.LoadEnv();
203 m_config.Source.Merge(envConfigSource); 225 m_config.Source.Merge(envConfigSource);
204 m_config.Source.ExpandKeyValues();
205 } 226 }
206 227
228 m_config.Source.ExpandKeyValues();
207 229
208 ReadConfigSettings(); 230 ReadConfigSettings();
209 231
@@ -214,10 +236,10 @@ namespace OpenSim
214 /// Adds the included files as ini configuration files 236 /// Adds the included files as ini configuration files
215 /// </summary> 237 /// </summary>
216 /// <param name="sources">List of URL strings or filename strings</param> 238 /// <param name="sources">List of URL strings or filename strings</param>
217 private void AddIncludes(List<string> sources) 239 private void AddIncludes(OpenSimConfigSource configSource, List<string> sources)
218 { 240 {
219 //loop over config sources 241 //loop over config sources
220 foreach (IConfig config in m_config.Source.Configs) 242 foreach (IConfig config in configSource.Source.Configs)
221 { 243 {
222 // Look for Include-* in the key name 244 // Look for Include-* in the key name
223 string[] keys = config.GetKeys(); 245 string[] keys = config.GetKeys();
@@ -284,7 +306,7 @@ namespace OpenSim
284 /// </summary> 306 /// </summary>
285 /// <param name="iniPath">Full path to the ini</param> 307 /// <param name="iniPath">Full path to the ini</param>
286 /// <returns></returns> 308 /// <returns></returns>
287 private bool ReadConfig(string iniPath) 309 private bool ReadConfig(OpenSimConfigSource configSource, string iniPath)
288 { 310 {
289 bool success = false; 311 bool success = false;
290 312
@@ -292,7 +314,7 @@ namespace OpenSim
292 { 314 {
293 m_log.InfoFormat("[CONFIG]: Reading configuration file {0}", Path.GetFullPath(iniPath)); 315 m_log.InfoFormat("[CONFIG]: Reading configuration file {0}", Path.GetFullPath(iniPath));
294 316
295 m_config.Source.Merge(new IniConfigSource(iniPath)); 317 configSource.Source.Merge(new IniConfigSource(iniPath));
296 success = true; 318 success = true;
297 } 319 }
298 else 320 else
@@ -305,7 +327,7 @@ namespace OpenSim
305 { 327 {
306 XmlReader r = XmlReader.Create(iniPath); 328 XmlReader r = XmlReader.Create(iniPath);
307 XmlConfigSource cs = new XmlConfigSource(r); 329 XmlConfigSource cs = new XmlConfigSource(r);
308 m_config.Source.Merge(cs); 330 configSource.Source.Merge(cs);
309 331
310 success = true; 332 success = true;
311 } 333 }
@@ -337,10 +359,7 @@ namespace OpenSim
337 config.Set("physics", "OpenDynamicsEngine"); 359 config.Set("physics", "OpenDynamicsEngine");
338 config.Set("meshing", "Meshmerizer"); 360 config.Set("meshing", "Meshmerizer");
339 config.Set("physical_prim", true); 361 config.Set("physical_prim", true);
340 config.Set("see_into_this_sim_from_neighbor", true);
341 config.Set("serverside_object_permissions", true); 362 config.Set("serverside_object_permissions", true);
342 config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
343 config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
344 config.Set("storage_prim_inventories", true); 363 config.Set("storage_prim_inventories", true);
345 config.Set("startup_console_commands_file", String.Empty); 364 config.Set("startup_console_commands_file", String.Empty);
346 config.Set("shutdown_console_commands_file", String.Empty); 365 config.Set("shutdown_console_commands_file", String.Empty);
@@ -372,7 +391,6 @@ namespace OpenSim
372 { 391 {
373 m_configSettings.PhysicsEngine = startupConfig.GetString("physics"); 392 m_configSettings.PhysicsEngine = startupConfig.GetString("physics");
374 m_configSettings.MeshEngineName = startupConfig.GetString("meshing"); 393 m_configSettings.MeshEngineName = startupConfig.GetString("meshing");
375 m_configSettings.StorageDll = startupConfig.GetString("storage_plugin");
376 394
377 m_configSettings.ClientstackDll 395 m_configSettings.ClientstackDll
378 = startupConfig.GetString("clientstack_plugin", "OpenSim.Region.ClientStack.LindenUDP.dll"); 396 = startupConfig.GetString("clientstack_plugin", "OpenSim.Region.ClientStack.LindenUDP.dll");
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index a7e7d03..85049c9 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -86,6 +86,7 @@ namespace OpenSim
86 IConfig startupConfig = Config.Configs["Startup"]; 86 IConfig startupConfig = Config.Configs["Startup"];
87 IConfig networkConfig = Config.Configs["Network"]; 87 IConfig networkConfig = Config.Configs["Network"];
88 88
89 int stpMinThreads = 2;
89 int stpMaxThreads = 15; 90 int stpMaxThreads = 15;
90 91
91 if (startupConfig != null) 92 if (startupConfig != null)
@@ -112,12 +113,13 @@ namespace OpenSim
112 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod)) 113 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
113 Util.FireAndForgetMethod = asyncCallMethod; 114 Util.FireAndForgetMethod = asyncCallMethod;
114 115
116 stpMinThreads = startupConfig.GetInt("MinPoolThreads", 15);
115 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15); 117 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15);
116 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) "); 118 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) ");
117 } 119 }
118 120
119 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) 121 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
120 Util.InitThreadPool(stpMaxThreads); 122 Util.InitThreadPool(stpMinThreads, stpMaxThreads);
121 123
122 m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod); 124 m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod);
123 } 125 }
@@ -170,6 +172,13 @@ namespace OpenSim
170 if (userStatsURI != String.Empty) 172 if (userStatsURI != String.Empty)
171 MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this)); 173 MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this));
172 174
175 if (managedStatsURI != String.Empty)
176 {
177 string urlBase = String.Format("/{0}/", managedStatsURI);
178 MainServer.Instance.AddHTTPHandler(urlBase, StatsManager.HandleStatsRequest);
179 m_log.InfoFormat("[OPENSIM] Enabling remote managed stats fetch. URL = {0}", urlBase);
180 }
181
173 if (m_console is RemoteConsole) 182 if (m_console is RemoteConsole)
174 { 183 {
175 if (m_consolePort == 0) 184 if (m_consolePort == 0)
@@ -226,41 +235,35 @@ namespace OpenSim
226 "Force the update of all objects on clients", 235 "Force the update of all objects on clients",
227 HandleForceUpdate); 236 HandleForceUpdate);
228 237
229 m_console.Commands.AddCommand("Debug", false, "debug packet",
230 "debug packet <level> [<avatar-first-name> <avatar-last-name>]",
231 "Turn on packet debugging",
232 "If level > 255 then all incoming and outgoing packets are logged.\n"
233 + "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n"
234 + "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n"
235 + "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n"
236 + "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n"
237 + "If level <= 0 then no packets are logged.\n"
238 + "If an avatar name is given then only packets from that avatar are logged",
239 Debug);
240
241 m_console.Commands.AddCommand("General", false, "change region", 238 m_console.Commands.AddCommand("General", false, "change region",
242 "change region <region name>", 239 "change region <region name>",
243 "Change current console region", ChangeSelectedRegion); 240 "Change current console region",
241 ChangeSelectedRegion);
244 242
245 m_console.Commands.AddCommand("Archiving", false, "save xml", 243 m_console.Commands.AddCommand("Archiving", false, "save xml",
246 "save xml", 244 "save xml",
247 "Save a region's data in XML format", SaveXml); 245 "Save a region's data in XML format",
246 SaveXml);
248 247
249 m_console.Commands.AddCommand("Archiving", false, "save xml2", 248 m_console.Commands.AddCommand("Archiving", false, "save xml2",
250 "save xml2", 249 "save xml2",
251 "Save a region's data in XML2 format", SaveXml2); 250 "Save a region's data in XML2 format",
251 SaveXml2);
252 252
253 m_console.Commands.AddCommand("Archiving", false, "load xml", 253 m_console.Commands.AddCommand("Archiving", false, "load xml",
254 "load xml [-newIDs [<x> <y> <z>]]", 254 "load xml [-newIDs [<x> <y> <z>]]",
255 "Load a region's data from XML format", LoadXml); 255 "Load a region's data from XML format",
256 LoadXml);
256 257
257 m_console.Commands.AddCommand("Archiving", false, "load xml2", 258 m_console.Commands.AddCommand("Archiving", false, "load xml2",
258 "load xml2", 259 "load xml2",
259 "Load a region's data from XML2 format", LoadXml2); 260 "Load a region's data from XML2 format",
261 LoadXml2);
260 262
261 m_console.Commands.AddCommand("Archiving", false, "save prims xml2", 263 m_console.Commands.AddCommand("Archiving", false, "save prims xml2",
262 "save prims xml2 [<prim name> <file name>]", 264 "save prims xml2 [<prim name> <file name>]",
263 "Save named prim to XML2", SavePrimsXml2); 265 "Save named prim to XML2",
266 SavePrimsXml2);
264 267
265 m_console.Commands.AddCommand("Archiving", false, "load oar", 268 m_console.Commands.AddCommand("Archiving", false, "load oar",
266 "load oar [--merge] [--skip-assets] [<OAR path>]", 269 "load oar [--merge] [--skip-assets] [<OAR path>]",
@@ -290,7 +293,23 @@ namespace OpenSim
290 293
291 m_console.Commands.AddCommand("Objects", false, "edit scale", 294 m_console.Commands.AddCommand("Objects", false, "edit scale",
292 "edit scale <name> <x> <y> <z>", 295 "edit scale <name> <x> <y> <z>",
293 "Change the scale of a named prim", HandleEditScale); 296 "Change the scale of a named prim",
297 HandleEditScale);
298
299 m_console.Commands.AddCommand("Objects", false, "rotate scene",
300 "rotate scene <degrees> [centerX, centerY]",
301 "Rotates all scene objects around centerX, centerY (defailt 128, 128) (please back up your region before using)",
302 HandleRotateScene);
303
304 m_console.Commands.AddCommand("Objects", false, "scale scene",
305 "scale scene <factor>",
306 "Scales the scene objects (please back up your region before using)",
307 HandleScaleScene);
308
309 m_console.Commands.AddCommand("Objects", false, "translate scene",
310 "translate scene xOffset yOffset zOffset",
311 "translates the scene objects (please back up your region before using)",
312 HandleTranslateScene);
294 313
295 m_console.Commands.AddCommand("Users", false, "kick user", 314 m_console.Commands.AddCommand("Users", false, "kick user",
296 "kick user <first> <last> [--force] [message]", 315 "kick user <first> <last> [--force] [message]",
@@ -308,31 +327,38 @@ namespace OpenSim
308 327
309 m_console.Commands.AddCommand("Comms", false, "show connections", 328 m_console.Commands.AddCommand("Comms", false, "show connections",
310 "show connections", 329 "show connections",
311 "Show connection data", HandleShow); 330 "Show connection data",
331 HandleShow);
312 332
313 m_console.Commands.AddCommand("Comms", false, "show circuits", 333 m_console.Commands.AddCommand("Comms", false, "show circuits",
314 "show circuits", 334 "show circuits",
315 "Show agent circuit data", HandleShow); 335 "Show agent circuit data",
336 HandleShow);
316 337
317 m_console.Commands.AddCommand("Comms", false, "show pending-objects", 338 m_console.Commands.AddCommand("Comms", false, "show pending-objects",
318 "show pending-objects", 339 "show pending-objects",
319 "Show # of objects on the pending queues of all scene viewers", HandleShow); 340 "Show # of objects on the pending queues of all scene viewers",
341 HandleShow);
320 342
321 m_console.Commands.AddCommand("General", false, "show modules", 343 m_console.Commands.AddCommand("General", false, "show modules",
322 "show modules", 344 "show modules",
323 "Show module data", HandleShow); 345 "Show module data",
346 HandleShow);
324 347
325 m_console.Commands.AddCommand("Regions", false, "show regions", 348 m_console.Commands.AddCommand("Regions", false, "show regions",
326 "show regions", 349 "show regions",
327 "Show region data", HandleShow); 350 "Show region data",
351 HandleShow);
328 352
329 m_console.Commands.AddCommand("Regions", false, "show ratings", 353 m_console.Commands.AddCommand("Regions", false, "show ratings",
330 "show ratings", 354 "show ratings",
331 "Show rating data", HandleShow); 355 "Show rating data",
356 HandleShow);
332 357
333 m_console.Commands.AddCommand("Objects", false, "backup", 358 m_console.Commands.AddCommand("Objects", false, "backup",
334 "backup", 359 "backup",
335 "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.", RunCommand); 360 "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.",
361 RunCommand);
336 362
337 m_console.Commands.AddCommand("Regions", false, "create region", 363 m_console.Commands.AddCommand("Regions", false, "create region",
338 "create region [\"region name\"] <region_file.ini>", 364 "create region [\"region name\"] <region_file.ini>",
@@ -345,34 +371,26 @@ namespace OpenSim
345 371
346 m_console.Commands.AddCommand("Regions", false, "restart", 372 m_console.Commands.AddCommand("Regions", false, "restart",
347 "restart", 373 "restart",
348 "Restart all sims in this instance", RunCommand); 374 "Restart all sims in this instance",
375 RunCommand);
349 376
350 m_console.Commands.AddCommand("General", false, "command-script", 377 m_console.Commands.AddCommand("General", false, "command-script",
351 "command-script <script>", 378 "command-script <script>",
352 "Run a command script from file", RunCommand); 379 "Run a command script from file",
380 RunCommand);
353 381
354 m_console.Commands.AddCommand("Regions", false, "remove-region", 382 m_console.Commands.AddCommand("Regions", false, "remove-region",
355 "remove-region <name>", 383 "remove-region <name>",
356 "Remove a region from this simulator", RunCommand); 384 "Remove a region from this simulator",
385 RunCommand);
357 386
358 m_console.Commands.AddCommand("Regions", false, "delete-region", 387 m_console.Commands.AddCommand("Regions", false, "delete-region",
359 "delete-region <name>", 388 "delete-region <name>",
360 "Delete a region from disk", RunCommand); 389 "Delete a region from disk",
361 390 RunCommand);
362 m_console.Commands.AddCommand("General", false, "modules list",
363 "modules list",
364 "List modules", HandleModules);
365
366 m_console.Commands.AddCommand("General", false, "modules load",
367 "modules load <name>",
368 "Load a module", HandleModules);
369
370 m_console.Commands.AddCommand("General", false, "modules unload",
371 "modules unload <name>",
372 "Unload a module", HandleModules);
373 } 391 }
374 392
375 public override void ShutdownSpecific() 393 protected override void ShutdownSpecific()
376 { 394 {
377 if (m_shutdownCommandsFile != String.Empty) 395 if (m_shutdownCommandsFile != String.Empty)
378 { 396 {
@@ -435,8 +453,8 @@ namespace OpenSim
435 { 453 {
436 RegionInfo regionInfo = presence.Scene.RegionInfo; 454 RegionInfo regionInfo = presence.Scene.RegionInfo;
437 455
438 if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && 456 if (presence.Firstname.ToLower().Equals(mainParams[2].ToLower()) &&
439 presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) 457 presence.Lastname.ToLower().Equals(mainParams[3].ToLower()))
440 { 458 {
441 MainConsole.Instance.Output( 459 MainConsole.Instance.Output(
442 String.Format( 460 String.Format(
@@ -449,7 +467,8 @@ namespace OpenSim
449 else 467 else
450 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); 468 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
451 469
452 presence.Scene.IncomingCloseAgent(presence.UUID, force); 470 presence.Scene.CloseAgent(presence.UUID, force);
471 break;
453 } 472 }
454 } 473 }
455 474
@@ -501,6 +520,121 @@ namespace OpenSim
501 } 520 }
502 } 521 }
503 522
523 private void HandleRotateScene(string module, string[] args)
524 {
525 string usage = "Usage: rotate scene <angle in degrees> [centerX centerY] (centerX and centerY are optional and default to Constants.RegionSize / 2";
526
527 float centerX = Constants.RegionSize * 0.5f;
528 float centerY = Constants.RegionSize * 0.5f;
529
530 if (args.Length < 3 || args.Length == 4)
531 {
532 MainConsole.Instance.Output(usage);
533 return;
534 }
535
536 float angle = (float)(Convert.ToSingle(args[2]) / 180.0 * Math.PI);
537 OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, angle);
538
539 if (args.Length > 4)
540 {
541 centerX = Convert.ToSingle(args[3]);
542 centerY = Convert.ToSingle(args[4]);
543 }
544
545 Vector3 center = new Vector3(centerX, centerY, 0.0f);
546
547 SceneManager.ForEachSelectedScene(delegate(Scene scene)
548 {
549 scene.ForEachSOG(delegate(SceneObjectGroup sog)
550 {
551 if (sog.AttachmentPoint == 0)
552 {
553 sog.RootPart.UpdateRotation(rot * sog.GroupRotation);
554 Vector3 offset = sog.AbsolutePosition - center;
555 offset *= rot;
556 sog.UpdateGroupPosition(center + offset);
557 }
558 });
559 });
560 }
561
562 private void HandleScaleScene(string module, string[] args)
563 {
564 string usage = "Usage: scale scene <factor>";
565
566 if (args.Length < 3)
567 {
568 MainConsole.Instance.Output(usage);
569 return;
570 }
571
572 float factor = (float)(Convert.ToSingle(args[2]));
573
574 float minZ = float.MaxValue;
575
576 SceneManager.ForEachSelectedScene(delegate(Scene scene)
577 {
578 scene.ForEachSOG(delegate(SceneObjectGroup sog)
579 {
580 if (sog.AttachmentPoint == 0)
581 {
582 if (sog.RootPart.AbsolutePosition.Z < minZ)
583 minZ = sog.RootPart.AbsolutePosition.Z;
584 }
585 });
586 });
587
588 SceneManager.ForEachSelectedScene(delegate(Scene scene)
589 {
590 scene.ForEachSOG(delegate(SceneObjectGroup sog)
591 {
592 if (sog.AttachmentPoint == 0)
593 {
594 Vector3 tmpRootPos = sog.RootPart.AbsolutePosition;
595 tmpRootPos.Z -= minZ;
596 tmpRootPos *= factor;
597 tmpRootPos.Z += minZ;
598
599 foreach (SceneObjectPart sop in sog.Parts)
600 {
601 if (sop.ParentID != 0)
602 sop.OffsetPosition *= factor;
603 sop.Scale *= factor;
604 }
605
606 sog.UpdateGroupPosition(tmpRootPos);
607 }
608 });
609 });
610 }
611
612 private void HandleTranslateScene(string module, string[] args)
613 {
614 string usage = "Usage: translate scene <xOffset, yOffset, zOffset>";
615
616 if (args.Length < 5)
617 {
618 MainConsole.Instance.Output(usage);
619 return;
620 }
621
622 float xOFfset = (float)Convert.ToSingle(args[2]);
623 float yOffset = (float)Convert.ToSingle(args[3]);
624 float zOffset = (float)Convert.ToSingle(args[4]);
625
626 Vector3 offset = new Vector3(xOFfset, yOffset, zOffset);
627
628 SceneManager.ForEachSelectedScene(delegate(Scene scene)
629 {
630 scene.ForEachSOG(delegate(SceneObjectGroup sog)
631 {
632 if (sog.AttachmentPoint == 0)
633 sog.UpdateGroupPosition(sog.AbsolutePosition + offset);
634 });
635 });
636 }
637
504 /// <summary> 638 /// <summary>
505 /// Creates a new region based on the parameters specified. This will ask the user questions on the console 639 /// Creates a new region based on the parameters specified. This will ask the user questions on the console
506 /// </summary> 640 /// </summary>
@@ -566,34 +700,6 @@ namespace OpenSim
566 } 700 }
567 701
568 /// <summary> 702 /// <summary>
569 /// Load, Unload, and list Region modules in use
570 /// </summary>
571 /// <param name="module"></param>
572 /// <param name="cmd"></param>
573 private void HandleModules(string module, string[] cmd)
574 {
575 List<string> args = new List<string>(cmd);
576 args.RemoveAt(0);
577 string[] cmdparams = args.ToArray();
578
579 if (cmdparams.Length > 0)
580 {
581 switch (cmdparams[0].ToLower())
582 {
583 case "list":
584 //TODO: Convert to new region modules
585 break;
586 case "unload":
587 //TODO: Convert to new region modules
588 break;
589 case "load":
590 //TODO: Convert to new region modules
591 break;
592 }
593 }
594 }
595
596 /// <summary>
597 /// Runs commands issued by the server console from the operator 703 /// Runs commands issued by the server console from the operator
598 /// </summary> 704 /// </summary>
599 /// <param name="command">The first argument of the parameter (the command)</param> 705 /// <param name="command">The first argument of the parameter (the command)</param>
@@ -701,45 +807,6 @@ namespace OpenSim
701 RefreshPrompt(); 807 RefreshPrompt();
702 } 808 }
703 809
704 /// <summary>
705 /// Turn on some debugging values for OpenSim.
706 /// </summary>
707 /// <param name="args"></param>
708 protected void Debug(string module, string[] args)
709 {
710 if (args.Length == 1)
711 return;
712
713 switch (args[1])
714 {
715 case "packet":
716 string name = null;
717 if (args.Length == 5)
718 name = string.Format("{0} {1}", args[3], args[4]);
719
720 if (args.Length > 2)
721 {
722 int newDebug;
723 if (int.TryParse(args[2], out newDebug))
724 {
725 SceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name);
726 // We provide user information elsewhere if any clients had their debug level set.
727// MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug);
728 }
729 else
730 {
731 MainConsole.Instance.Output("Usage: debug packet 0..255");
732 }
733 }
734
735 break;
736
737 default:
738 MainConsole.Instance.Output("Unknown debug command");
739 break;
740 }
741 }
742
743 // see BaseOpenSimServer 810 // see BaseOpenSimServer
744 /// <summary> 811 /// <summary>
745 /// Many commands list objects for debugging. Some of the types are listed here 812 /// Many commands list objects for debugging. Some of the types are listed here
@@ -829,7 +896,7 @@ namespace OpenSim
829 foreach (IRegionModuleBase module in sharedModules.OrderBy(m => m.Name)) 896 foreach (IRegionModuleBase module in sharedModules.OrderBy(m => m.Name))
830 MainConsole.Instance.OutputFormat("New Region Module (Shared): {0}", module.Name); 897 MainConsole.Instance.OutputFormat("New Region Module (Shared): {0}", module.Name);
831 898
832 foreach (IRegionModuleBase module in sharedModules.OrderBy(m => m.Name)) 899 foreach (IRegionModuleBase module in nonSharedModules.OrderBy(m => m.Name))
833 MainConsole.Instance.OutputFormat("New Region Module (Non-Shared): {0}", module.Name); 900 MainConsole.Instance.OutputFormat("New Region Module (Non-Shared): {0}", module.Name);
834 } 901 }
835 ); 902 );
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 88bd869..f663c77 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -75,6 +75,7 @@ namespace OpenSim
75 protected int proxyOffset = 0; 75 protected int proxyOffset = 0;
76 76
77 public string userStatsURI = String.Empty; 77 public string userStatsURI = String.Empty;
78 public string managedStatsURI = String.Empty;
78 79
79 protected bool m_autoCreateClientStack = true; 80 protected bool m_autoCreateClientStack = true;
80 81
@@ -199,6 +200,8 @@ namespace OpenSim
199 new string[] { "Startup", "Permissions" }, "DefaultPermissionsModule"); 200 new string[] { "Startup", "Permissions" }, "DefaultPermissionsModule");
200 201
201 m_permsModules = new List<string>(permissionModules.Split(',')); 202 m_permsModules = new List<string>(permissionModules.Split(','));
203
204 managedStatsURI = startupConfig.GetString("ManagedStatsRemoteFetchURI", String.Empty);
202 } 205 }
203 206
204 // Load the simulation data service 207 // Load the simulation data service
@@ -248,10 +251,7 @@ namespace OpenSim
248 } 251 }
249 252
250 if (m_console != null) 253 if (m_console != null)
251 {
252 StatsManager.RegisterConsoleCommands(m_console);
253 AddPluginCommands(m_console); 254 AddPluginCommands(m_console);
254 }
255 } 255 }
256 256
257 protected virtual void AddPluginCommands(ICommandConsole console) 257 protected virtual void AddPluginCommands(ICommandConsole console)
@@ -496,9 +496,6 @@ namespace OpenSim
496 scene.SnmpService.LinkUp(scene); 496 scene.SnmpService.LinkUp(scene);
497 } 497 }
498 498
499 scene.Start();
500 scene.StartScripts();
501
502 return clientServers; 499 return clientServers;
503 } 500 }
504 501
@@ -813,7 +810,7 @@ namespace OpenSim
813 810
814 if (foundClientServer) 811 if (foundClientServer)
815 { 812 {
816 m_clientServers[clientServerElement].NetworkStop(); 813 m_clientServers[clientServerElement].Stop();
817 m_clientServers.RemoveAt(clientServerElement); 814 m_clientServers.RemoveAt(clientServerElement);
818 } 815 }
819 } 816 }
@@ -827,6 +824,7 @@ namespace OpenSim
827 ShutdownClientServer(whichRegion); 824 ShutdownClientServer(whichRegion);
828 IScene scene; 825 IScene scene;
829 CreateRegion(whichRegion, true, out scene); 826 CreateRegion(whichRegion, true, out scene);
827 scene.Start();
830 } 828 }
831 829
832 # region Setup methods 830 # region Setup methods
@@ -840,73 +838,49 @@ namespace OpenSim
840 /// <summary> 838 /// <summary>
841 /// Handler to supply the current status of this sim 839 /// Handler to supply the current status of this sim
842 /// </summary> 840 /// </summary>
841 /// <remarks>
843 /// Currently this is always OK if the simulator is still listening for connections on its HTTP service 842 /// Currently this is always OK if the simulator is still listening for connections on its HTTP service
844 public class SimStatusHandler : IStreamedRequestHandler 843 /// </remarks>
844 public class SimStatusHandler : BaseStreamHandler
845 { 845 {
846 public byte[] Handle(string path, Stream request, 846 public SimStatusHandler() : base("GET", "/simstatus", "SimStatus", "Simulator Status") {}
847
848 protected override byte[] ProcessRequest(string path, Stream request,
847 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 849 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
848 { 850 {
849 return Util.UTF8.GetBytes("OK"); 851 return Util.UTF8.GetBytes("OK");
850 } 852 }
851 853
852 public string Name { get { return "SimStatus"; } } 854 public override string ContentType
853 public string Description { get { return "Simulator Status"; } }
854
855 public string ContentType
856 { 855 {
857 get { return "text/plain"; } 856 get { return "text/plain"; }
858 } 857 }
859
860 public string HttpMethod
861 {
862 get { return "GET"; }
863 }
864
865 public string Path
866 {
867 get { return "/simstatus"; }
868 }
869 } 858 }
870 859
871 /// <summary> 860 /// <summary>
872 /// Handler to supply the current extended status of this sim 861 /// Handler to supply the current extended status of this sim
873 /// Sends the statistical data in a json serialization 862 /// Sends the statistical data in a json serialization
874 /// </summary> 863 /// </summary>
875 public class XSimStatusHandler : IStreamedRequestHandler 864 public class XSimStatusHandler : BaseStreamHandler
876 { 865 {
877 OpenSimBase m_opensim; 866 OpenSimBase m_opensim;
878 string osXStatsURI = String.Empty;
879
880 public string Name { get { return "XSimStatus"; } }
881 public string Description { get { return "Simulator XStatus"; } }
882 867
883 public XSimStatusHandler(OpenSimBase sim) 868 public XSimStatusHandler(OpenSimBase sim)
869 : base("GET", "/" + Util.SHA1Hash(sim.osSecret), "XSimStatus", "Simulator XStatus")
884 { 870 {
885 m_opensim = sim; 871 m_opensim = sim;
886 osXStatsURI = Util.SHA1Hash(sim.osSecret);
887 } 872 }
888 873
889 public byte[] Handle(string path, Stream request, 874 protected override byte[] ProcessRequest(string path, Stream request,
890 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 875 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
891 { 876 {
892 return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest)); 877 return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest));
893 } 878 }
894 879
895 public string ContentType 880 public override string ContentType
896 { 881 {
897 get { return "text/plain"; } 882 get { return "text/plain"; }
898 } 883 }
899
900 public string HttpMethod
901 {
902 get { return "GET"; }
903 }
904
905 public string Path
906 {
907 // This is for the OpenSimulator instance and is the osSecret hashed
908 get { return "/" + osXStatsURI; }
909 }
910 } 884 }
911 885
912 /// <summary> 886 /// <summary>
@@ -915,42 +889,26 @@ namespace OpenSim
915 /// If the request contains a key, "callback" the response will be wrappend in the 889 /// If the request contains a key, "callback" the response will be wrappend in the
916 /// associated value for jsonp used with ajax/javascript 890 /// associated value for jsonp used with ajax/javascript
917 /// </summary> 891 /// </summary>
918 public class UXSimStatusHandler : IStreamedRequestHandler 892 protected class UXSimStatusHandler : BaseStreamHandler
919 { 893 {
920 OpenSimBase m_opensim; 894 OpenSimBase m_opensim;
921 string osUXStatsURI = String.Empty;
922
923 public string Name { get { return "UXSimStatus"; } }
924 public string Description { get { return "Simulator UXStatus"; } }
925 895
926 public UXSimStatusHandler(OpenSimBase sim) 896 public UXSimStatusHandler(OpenSimBase sim)
897 : base("GET", "/" + sim.userStatsURI, "UXSimStatus", "Simulator UXStatus")
927 { 898 {
928 m_opensim = sim; 899 m_opensim = sim;
929 osUXStatsURI = sim.userStatsURI;
930
931 } 900 }
932 901
933 public byte[] Handle(string path, Stream request, 902 protected override byte[] ProcessRequest(string path, Stream request,
934 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 903 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
935 { 904 {
936 return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest)); 905 return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest));
937 } 906 }
938 907
939 public string ContentType 908 public override string ContentType
940 { 909 {
941 get { return "text/plain"; } 910 get { return "text/plain"; }
942 } 911 }
943
944 public string HttpMethod
945 {
946 get { return "GET"; }
947 }
948
949 public string Path
950 {
951 // This is for the OpenSimulator instance and is the user provided URI
952 get { return "/" + osUXStatsURI; }
953 }
954 } 912 }
955 913
956 #endregion 914 #endregion
@@ -958,7 +916,7 @@ namespace OpenSim
958 /// <summary> 916 /// <summary>
959 /// Performs any last-minute sanity checking and shuts down the region server 917 /// Performs any last-minute sanity checking and shuts down the region server
960 /// </summary> 918 /// </summary>
961 public override void ShutdownSpecific() 919 protected override void ShutdownSpecific()
962 { 920 {
963 if (proxyUrl.Length > 0) 921 if (proxyUrl.Length > 0)
964 { 922 {
@@ -978,6 +936,8 @@ namespace OpenSim
978 { 936 {
979 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e); 937 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
980 } 938 }
939
940 base.ShutdownSpecific();
981 } 941 }
982 942
983 /// <summary> 943 /// <summary>
@@ -1025,7 +985,7 @@ namespace OpenSim
1025 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, true); 985 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, true);
1026 986
1027 string newName; 987 string newName;
1028 if (estateName != null && estateName != "") 988 if (!string.IsNullOrEmpty(estateName))
1029 newName = estateName; 989 newName = estateName;
1030 else 990 else
1031 newName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName); 991 newName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName);
diff --git a/OpenSim/Region/ClientStack/IClientNetworkServer.cs b/OpenSim/Region/ClientStack/IClientNetworkServer.cs
index 54a441b..bb7e6d0 100644
--- a/OpenSim/Region/ClientStack/IClientNetworkServer.cs
+++ b/OpenSim/Region/ClientStack/IClientNetworkServer.cs
@@ -38,11 +38,22 @@ namespace OpenSim.Region.ClientStack
38 IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, 38 IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource,
39 AgentCircuitManager authenticateClass); 39 AgentCircuitManager authenticateClass);
40 40
41 void NetworkStop();
42 bool HandlesRegion(Location x); 41 bool HandlesRegion(Location x);
43 void AddScene(IScene x);
44 42
43 /// <summary>
44 /// Add the given scene to be handled by this IClientNetworkServer.
45 /// </summary>
46 /// <param name='scene'></param>
47 void AddScene(IScene scene);
48
49 /// <summary>
50 /// Start sending and receiving data.
51 /// </summary>
45 void Start(); 52 void Start();
53
54 /// <summary>
55 /// Stop sending and receiving data.
56 /// </summary>
46 void Stop(); 57 void Stop();
47 } 58 }
48} 59}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs
new file mode 100644
index 0000000..bbadc55
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs
@@ -0,0 +1,136 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Specialized;
31using System.Drawing;
32using System.Drawing.Imaging;
33using System.Reflection;
34using System.IO;
35using System.Web;
36using log4net;
37using Nini.Config;
38using Mono.Addins;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenSim.Framework;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Services.Interfaces;
47using Caps = OpenSim.Framework.Capabilities.Caps;
48using OpenSim.Capabilities.Handlers;
49
50namespace OpenSim.Region.ClientStack.Linden
51{
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AvatarPickerSearchModule")]
53 public class AvatarPickerSearchModule : INonSharedRegionModule
54 {
55// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 private Scene m_scene;
58 private IPeople m_People;
59 private bool m_Enabled = false;
60
61 private string m_URL;
62
63 #region ISharedRegionModule Members
64
65 public void Initialise(IConfigSource source)
66 {
67 IConfig config = source.Configs["ClientStack.LindenCaps"];
68 if (config == null)
69 return;
70
71 m_URL = config.GetString("Cap_AvatarPickerSearch", string.Empty);
72 // Cap doesn't exist
73 if (m_URL != string.Empty)
74 m_Enabled = true;
75 }
76
77 public void AddRegion(Scene s)
78 {
79 if (!m_Enabled)
80 return;
81
82 m_scene = s;
83 }
84
85 public void RemoveRegion(Scene s)
86 {
87 if (!m_Enabled)
88 return;
89
90 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
91 m_scene = null;
92 }
93
94 public void RegionLoaded(Scene s)
95 {
96 if (!m_Enabled)
97 return;
98
99 m_People = m_scene.RequestModuleInterface<IPeople>();
100 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
101 }
102
103 public void PostInitialise()
104 {
105 }
106
107 public void Close() { }
108
109 public string Name { get { return "AvatarPickerSearchModule"; } }
110
111 public Type ReplaceableInterface
112 {
113 get { return null; }
114 }
115
116 #endregion
117
118 public void RegisterCaps(UUID agentID, Caps caps)
119 {
120 UUID capID = UUID.Random();
121
122 if (m_URL == "localhost")
123 {
124// m_log.DebugFormat("[AVATAR PICKER SEARCH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
125 caps.RegisterHandler(
126 "AvatarPickerSearch",
127 new AvatarPickerSearchHandler("/CAPS/" + capID + "/", m_People, "AvatarPickerSearch", "Search for avatars by name"));
128 }
129 else
130 {
131 // m_log.DebugFormat("[AVATAR PICKER SEARCH]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName);
132 caps.RegisterHandler("AvatarPickerSearch", m_URL);
133 }
134 }
135 }
136} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 8241e07..613bc24 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -282,13 +282,19 @@ namespace OpenSim.Region.ClientStack.Linden
282 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); 282 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
283 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); 283 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
284 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); 284 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
285 IRequestHandler getObjectPhysicsDataHandler = new RestStreamHandler("POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData); 285
286 IRequestHandler getObjectPhysicsDataHandler
287 = new RestStreamHandler(
288 "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
286 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler); 289 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
287 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost); 290 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
288 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler); 291 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
289 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected); 292 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
290 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler); 293 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
291 IRequestHandler UpdateAgentInformationHandler = new RestStreamHandler("POST", capsBase + m_UpdateAgentInformationPath, UpdateAgentInformation); 294
295 IRequestHandler UpdateAgentInformationHandler
296 = new RestStreamHandler(
297 "POST", capsBase + m_UpdateAgentInformationPath, UpdateAgentInformation, "UpdateAgentInformation", null);
292 m_HostCapsObj.RegisterHandler("UpdateAgentInformation", UpdateAgentInformationHandler); 298 m_HostCapsObj.RegisterHandler("UpdateAgentInformation", UpdateAgentInformationHandler);
293 299
294 m_HostCapsObj.RegisterHandler( 300 m_HostCapsObj.RegisterHandler(
@@ -361,18 +367,7 @@ namespace OpenSim.Region.ClientStack.Linden
361 foreach (OSD c in capsRequested) 367 foreach (OSD c in capsRequested)
362 validCaps.Add(c.AsString()); 368 validCaps.Add(c.AsString());
363 369
364 Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true, validCaps); 370 string result = LLSDHelpers.SerialiseLLSDReply(m_HostCapsObj.GetCapsDetails(true, validCaps));
365
366 // Add the external too
367 foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
368 {
369 if (!validCaps.Contains(kvp.Key))
370 continue;
371
372 caps[kvp.Key] = kvp.Value;
373 }
374
375 string result = LLSDHelpers.SerialiseLLSDReply(caps);
376 371
377 //m_log.DebugFormat("[CAPS] CapsRequest {0}", result); 372 //m_log.DebugFormat("[CAPS] CapsRequest {0}", result);
378 373
@@ -748,6 +743,10 @@ namespace OpenSim.Region.ClientStack.Linden
748 inType = (sbyte)InventoryType.Sound; 743 inType = (sbyte)InventoryType.Sound;
749 assType = (sbyte)AssetType.Sound; 744 assType = (sbyte)AssetType.Sound;
750 } 745 }
746 else if (inventoryType == "snapshot")
747 {
748 inType = (sbyte)InventoryType.Snapshot;
749 }
751 else if (inventoryType == "animation") 750 else if (inventoryType == "animation")
752 { 751 {
753 inType = (sbyte)InventoryType.Animation; 752 inType = (sbyte)InventoryType.Animation;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index eb40eb1..ffb53af 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -65,6 +65,13 @@ namespace OpenSim.Region.ClientStack.Linden
65 /// </value> 65 /// </value>
66 public int DebugLevel { get; set; } 66 public int DebugLevel { get; set; }
67 67
68 // Viewer post requests timeout in 60 secs
69 // https://bitbucket.org/lindenlab/viewer-release/src/421c20423df93d650cc305dc115922bb30040999/indra/llmessage/llhttpclient.cpp?at=default#cl-44
70 //
71 private const int VIEWER_TIMEOUT = 60 * 1000;
72 // Just to be safe, we work on a 10 sec shorter cycle
73 private const int SERVER_EQ_TIME_NO_EVENTS = VIEWER_TIMEOUT - (10 * 1000);
74
68 protected Scene m_scene; 75 protected Scene m_scene;
69 76
70 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); 77 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
@@ -84,7 +91,6 @@ namespace OpenSim.Region.ClientStack.Linden
84 scene.RegisterModuleInterface<IEventQueue>(this); 91 scene.RegisterModuleInterface<IEventQueue>(this);
85 92
86 scene.EventManager.OnClientClosed += ClientClosed; 93 scene.EventManager.OnClientClosed += ClientClosed;
87 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
88 scene.EventManager.OnRegisterCaps += OnRegisterCaps; 94 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
89 95
90 MainConsole.Instance.Commands.AddCommand( 96 MainConsole.Instance.Commands.AddCommand(
@@ -113,7 +119,6 @@ namespace OpenSim.Region.ClientStack.Linden
113 return; 119 return;
114 120
115 scene.EventManager.OnClientClosed -= ClientClosed; 121 scene.EventManager.OnClientClosed -= ClientClosed;
116 scene.EventManager.OnMakeChildAgent -= MakeChildAgent;
117 scene.EventManager.OnRegisterCaps -= OnRegisterCaps; 122 scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
118 123
119 scene.UnregisterModuleInterface<IEventQueue>(this); 124 scene.UnregisterModuleInterface<IEventQueue>(this);
@@ -182,14 +187,12 @@ namespace OpenSim.Region.ClientStack.Linden
182 { 187 {
183 if (!queues.ContainsKey(agentId)) 188 if (!queues.ContainsKey(agentId))
184 { 189 {
185 /*
186 m_log.DebugFormat( 190 m_log.DebugFormat(
187 "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}", 191 "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}",
188 agentId, m_scene.RegionInfo.RegionName); 192 agentId, m_scene.RegionInfo.RegionName);
189 */
190 queues[agentId] = new Queue<OSD>(); 193 queues[agentId] = new Queue<OSD>();
191 } 194 }
192 195
193 return queues[agentId]; 196 return queues[agentId];
194 } 197 }
195 } 198 }
@@ -221,8 +224,17 @@ namespace OpenSim.Region.ClientStack.Linden
221 { 224 {
222 Queue<OSD> queue = GetQueue(avatarID); 225 Queue<OSD> queue = GetQueue(avatarID);
223 if (queue != null) 226 if (queue != null)
227 {
224 lock (queue) 228 lock (queue)
225 queue.Enqueue(ev); 229 queue.Enqueue(ev);
230 }
231 else
232 {
233 OSDMap evMap = (OSDMap)ev;
234 m_log.WarnFormat(
235 "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} when placing message {1} in region {2}",
236 avatarID, evMap["message"], m_scene.Name);
237 }
226 } 238 }
227 catch (NullReferenceException e) 239 catch (NullReferenceException e)
228 { 240 {
@@ -237,44 +249,14 @@ namespace OpenSim.Region.ClientStack.Linden
237 249
238 private void ClientClosed(UUID agentID, Scene scene) 250 private void ClientClosed(UUID agentID, Scene scene)
239 { 251 {
240// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); 252 //m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
241
242 int count = 0;
243 while (queues.ContainsKey(agentID) && queues[agentID].Count > 0 && count++ < 5)
244 {
245 Thread.Sleep(1000);
246 }
247 253
248 lock (queues) 254 lock (queues)
249 {
250 queues.Remove(agentID); 255 queues.Remove(agentID);
251 }
252 256
253 List<UUID> removeitems = new List<UUID>(); 257 List<UUID> removeitems = new List<UUID>();
254 lock (m_AvatarQueueUUIDMapping) 258 lock (m_AvatarQueueUUIDMapping)
255 { 259 m_AvatarQueueUUIDMapping.Remove(agentID);
256 foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
257 {
258// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
259 if (ky == agentID)
260 {
261 removeitems.Add(ky);
262 }
263 }
264
265 foreach (UUID ky in removeitems)
266 {
267 UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky];
268 m_AvatarQueueUUIDMapping.Remove(ky);
269
270 string eqgPath = GenerateEqgCapPath(eventQueueGetUuid);
271 MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath);
272
273// m_log.DebugFormat(
274// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}",
275// eqgPath, agentID, m_scene.RegionInfo.RegionName);
276 }
277 }
278 260
279 UUID searchval = UUID.Zero; 261 UUID searchval = UUID.Zero;
280 262
@@ -295,19 +277,9 @@ namespace OpenSim.Region.ClientStack.Linden
295 foreach (UUID ky in removeitems) 277 foreach (UUID ky in removeitems)
296 m_QueueUUIDAvatarMapping.Remove(ky); 278 m_QueueUUIDAvatarMapping.Remove(ky);
297 } 279 }
298 }
299 280
300 private void MakeChildAgent(ScenePresence avatar) 281 // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
301 { 282
302 //m_log.DebugFormat("[EVENTQUEUE]: Make Child agent {0} in region {1}.", avatar.UUID, m_scene.RegionInfo.RegionName);
303 //lock (m_ids)
304 // {
305 //if (m_ids.ContainsKey(avatar.UUID))
306 //{
307 // close the event queue.
308 //m_ids[avatar.UUID] = -1;
309 //}
310 //}
311 } 283 }
312 284
313 /// <summary> 285 /// <summary>
@@ -323,9 +295,9 @@ namespace OpenSim.Region.ClientStack.Linden
323 { 295 {
324 // Register an event queue for the client 296 // Register an event queue for the client
325 297
326 //m_log.DebugFormat( 298 m_log.DebugFormat(
327 // "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", 299 "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
328 // agentID, caps, m_scene.RegionInfo.RegionName); 300 agentID, caps, m_scene.RegionInfo.RegionName);
329 301
330 // Let's instantiate a Queue for this agent right now 302 // Let's instantiate a Queue for this agent right now
331 TryGetQueue(agentID); 303 TryGetQueue(agentID);
@@ -359,28 +331,9 @@ namespace OpenSim.Region.ClientStack.Linden
359 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); 331 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
360 } 332 }
361 333
362 string eventQueueGetPath = GenerateEqgCapPath(eventQueueGetUUID); 334 caps.RegisterPollHandler(
363 335 "EventQueueGet",
364 // Register this as a caps handler 336 new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS));
365 // FIXME: Confusingly, we need to register separate as a capability so that the client is told about
366 // EventQueueGet when it receive capability information, but then we replace the rest handler immediately
367 // afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but
368 // really it should be possible to directly register the poll handler as a capability.
369 caps.RegisterHandler("EventQueueGet", new RestHTTPHandler("POST", eventQueueGetPath, null));
370// delegate(Hashtable m_dhttpMethod)
371// {
372// return ProcessQueue(m_dhttpMethod, agentID, caps);
373// }));
374
375 // This will persist this beyond the expiry of the caps handlers
376 // TODO: Add EventQueueGet name/description for diagnostics
377 MainServer.Instance.AddPollServiceHTTPHandler(
378 eventQueueGetPath,
379 new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID, 40000));
380
381// m_log.DebugFormat(
382// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
383// eventQueueGetPath, agentID, m_scene.RegionInfo.RegionName);
384 337
385 Random rnd = new Random(Environment.TickCount); 338 Random rnd = new Random(Environment.TickCount);
386 lock (m_ids) 339 lock (m_ids)
@@ -398,7 +351,10 @@ namespace OpenSim.Region.ClientStack.Linden
398 Queue<OSD> queue = GetQueue(agentID); 351 Queue<OSD> queue = GetQueue(agentID);
399 if (queue != null) 352 if (queue != null)
400 lock (queue) 353 lock (queue)
354 {
355 //m_log.WarnFormat("POLLED FOR EVENTS BY {0} in {1} -- {2}", agentID, m_scene.RegionInfo.RegionName, queue.Count);
401 return queue.Count > 0; 356 return queue.Count > 0;
357 }
402 358
403 return false; 359 return false;
404 } 360 }
@@ -414,16 +370,21 @@ namespace OpenSim.Region.ClientStack.Linden
414 OSDMap ev = (OSDMap)element; 370 OSDMap ev = (OSDMap)element;
415 m_log.DebugFormat( 371 m_log.DebugFormat(
416 "Eq OUT {0,-30} to {1,-20} {2,-20}", 372 "Eq OUT {0,-30} to {1,-20} {2,-20}",
417 ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.RegionInfo.RegionName); 373 ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.Name);
418 } 374 }
419 } 375 }
420 376
421 public Hashtable GetEvents(UUID requestID, UUID pAgentId) 377 public Hashtable GetEvents(UUID requestID, UUID pAgentId)
422 { 378 {
423 if (DebugLevel >= 2) 379 if (DebugLevel >= 2)
424 m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName); 380 m_log.WarnFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.Name);
381
382 Queue<OSD> queue = GetQueue(pAgentId);
383 if (queue == null)
384 {
385 return NoEvents(requestID, pAgentId);
386 }
425 387
426 Queue<OSD> queue = TryGetQueue(pAgentId);
427 OSD element; 388 OSD element;
428 lock (queue) 389 lock (queue)
429 { 390 {
@@ -750,34 +711,46 @@ namespace OpenSim.Region.ClientStack.Linden
750 Enqueue(item, avatarID); 711 Enqueue(item, avatarID);
751 } 712 }
752 713
753 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID) 714 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
754 { 715 {
755 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint); 716 m_log.DebugFormat("{0} EnableSimulator. handle={1}, avatarID={2}, regionSize={3},{4}>",
717 "[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY);
718
719 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY);
756 Enqueue(item, avatarID); 720 Enqueue(item, avatarID);
757 } 721 }
758 722
759 public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath) 723 public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath,
724 ulong regionHandle, int regionSizeX, int regionSizeY)
760 { 725 {
761 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath); 726 m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, avatarID={2}, regionSize={3},{4}>",
727 "[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY);
728 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY);
762 Enqueue(item, avatarID); 729 Enqueue(item, avatarID);
763 } 730 }
764 731
765 public virtual void TeleportFinishEvent(ulong regionHandle, byte simAccess, 732 public virtual void TeleportFinishEvent(ulong regionHandle, byte simAccess,
766 IPEndPoint regionExternalEndPoint, 733 IPEndPoint regionExternalEndPoint,
767 uint locationID, uint flags, string capsURL, 734 uint locationID, uint flags, string capsURL,
768 UUID avatarID) 735 UUID avatarID, int regionSizeX, int regionSizeY)
769 { 736 {
737 m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, avatarID={2}, regionSize={3},{4}>",
738 "[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY);
739
770 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint, 740 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
771 locationID, flags, capsURL, avatarID); 741 locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY);
772 Enqueue(item, avatarID); 742 Enqueue(item, avatarID);
773 } 743 }
774 744
775 public virtual void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, 745 public virtual void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
776 IPEndPoint newRegionExternalEndPoint, 746 IPEndPoint newRegionExternalEndPoint,
777 string capsURL, UUID avatarID, UUID sessionID) 747 string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
778 { 748 {
749 m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>",
750 "[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY);
751
779 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint, 752 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
780 capsURL, avatarID, sessionID); 753 capsURL, avatarID, sessionID, regionSizeX, regionSizeY);
781 Enqueue(item, avatarID); 754 Enqueue(item, avatarID);
782 } 755 }
783 756
@@ -794,12 +767,12 @@ namespace OpenSim.Region.ClientStack.Linden
794 767
795 } 768 }
796 769
797 public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat, 770 public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat,
798 bool isModerator, bool textMute) 771 bool isModerator, bool textMute)
799 { 772 {
800 OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat, 773 OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat,
801 isModerator, textMute); 774 isModerator, textMute);
802 Enqueue(item, toAgent); 775 Enqueue(item, fromAgent);
803 //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item); 776 //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item);
804 } 777 }
805 778
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
index 7dcf137..3fb7de2 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
@@ -70,13 +70,15 @@ namespace OpenSim.Region.ClientStack.Linden
70 return llsdEvent; 70 return llsdEvent;
71 } 71 }
72 72
73 public static OSD EnableSimulator(ulong handle, IPEndPoint endPoint) 73 public static OSD EnableSimulator(ulong handle, IPEndPoint endPoint, int regionSizeX, int regionSizeY)
74 { 74 {
75 OSDMap llsdSimInfo = new OSDMap(3); 75 OSDMap llsdSimInfo = new OSDMap(5);
76 76
77 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle))); 77 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle)));
78 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes())); 78 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes()));
79 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port)); 79 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port));
80 llsdSimInfo.Add("RegionSizeX", new OSDInteger(regionSizeX));
81 llsdSimInfo.Add("RegionSizeY", new OSDInteger(regionSizeY));
80 82
81 OSDArray arr = new OSDArray(1); 83 OSDArray arr = new OSDArray(1);
82 arr.Add(llsdSimInfo); 84 arr.Add(llsdSimInfo);
@@ -104,7 +106,8 @@ namespace OpenSim.Region.ClientStack.Linden
104 106
105 public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, 107 public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
106 IPEndPoint newRegionExternalEndPoint, 108 IPEndPoint newRegionExternalEndPoint,
107 string capsURL, UUID agentID, UUID sessionID) 109 string capsURL, UUID agentID, UUID sessionID,
110 int regionSizeX, int regionSizeY)
108 { 111 {
109 OSDArray lookAtArr = new OSDArray(3); 112 OSDArray lookAtArr = new OSDArray(3);
110 lookAtArr.Add(OSD.FromReal(lookAt.X)); 113 lookAtArr.Add(OSD.FromReal(lookAt.X));
@@ -130,11 +133,13 @@ namespace OpenSim.Region.ClientStack.Linden
130 OSDArray agentDataArr = new OSDArray(1); 133 OSDArray agentDataArr = new OSDArray(1);
131 agentDataArr.Add(agentDataMap); 134 agentDataArr.Add(agentDataMap);
132 135
133 OSDMap regionDataMap = new OSDMap(4); 136 OSDMap regionDataMap = new OSDMap(6);
134 regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle))); 137 regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle)));
135 regionDataMap.Add("SeedCapability", OSD.FromString(capsURL)); 138 regionDataMap.Add("SeedCapability", OSD.FromString(capsURL));
136 regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes())); 139 regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes()));
137 regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port)); 140 regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port));
141 regionDataMap.Add("RegionSizeX", new OSDInteger(regionSizeX));
142 regionDataMap.Add("RegionSizeY", new OSDInteger(regionSizeY));
138 143
139 OSDArray regionDataArr = new OSDArray(1); 144 OSDArray regionDataArr = new OSDArray(1);
140 regionDataArr.Add(regionDataMap); 145 regionDataArr.Add(regionDataMap);
@@ -148,8 +153,9 @@ namespace OpenSim.Region.ClientStack.Linden
148 } 153 }
149 154
150 public static OSD TeleportFinishEvent( 155 public static OSD TeleportFinishEvent(
151 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, 156 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
152 uint locationID, uint flags, string capsURL, UUID agentID) 157 uint locationID, uint flags, string capsURL, UUID agentID,
158 int regionSizeX, int regionSizeY)
153 { 159 {
154 // not sure why flags get overwritten here 160 // not sure why flags get overwritten here
155 if ((flags & (uint)TeleportFlags.IsFlying) != 0) 161 if ((flags & (uint)TeleportFlags.IsFlying) != 0)
@@ -167,6 +173,8 @@ namespace OpenSim.Region.ClientStack.Linden
167 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port)); 173 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
168// info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation 174// info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
169 info.Add("TeleportFlags", OSD.FromUInteger(flags)); 175 info.Add("TeleportFlags", OSD.FromUInteger(flags));
176 info.Add("RegionSizeX", new OSDInteger(regionSizeX));
177 info.Add("RegionSizeY", new OSDInteger(regionSizeY));
170 178
171 OSDArray infoArr = new OSDArray(); 179 OSDArray infoArr = new OSDArray();
172 infoArr.Add(info); 180 infoArr.Add(info);
@@ -194,12 +202,18 @@ namespace OpenSim.Region.ClientStack.Linden
194 return BuildEvent("ScriptRunningReply", body); 202 return BuildEvent("ScriptRunningReply", body);
195 } 203 }
196 204
197 public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap) 205 public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap,
206 ulong regionHandle, int regionSizeX, int regionSizeY)
198 { 207 {
199 OSDMap body = new OSDMap(3); 208 OSDMap body = new OSDMap(6)
200 body.Add("agent-id", new OSDUUID(agentID)); 209 {
201 body.Add("sim-ip-and-port", new OSDString(simIpAndPort)); 210 {"agent-id", new OSDUUID(agentID)},
202 body.Add("seed-capability", new OSDString(seedcap)); 211 {"sim-ip-and-port", new OSDString(simIpAndPort)},
212 {"seed-capability", new OSDString(seedcap)},
213 {"region-handle", OSD.FromULong(regionHandle)},
214 {"region-size-x", OSD.FromInteger(regionSizeX)},
215 {"region-size-y", OSD.FromInteger(regionSizeY)}
216 };
203 217
204 return BuildEvent("EstablishAgentCommunication", body); 218 return BuildEvent("EstablishAgentCommunication", body);
205 } 219 }
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index 141af8a..9e24bce 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
76 } 76 }
77 77
78 [Test] 78 [Test]
79 public void AddForClient() 79 public void TestAddForClient()
80 { 80 {
81 TestHelpers.InMethod(); 81 TestHelpers.InMethod();
82// log4net.Config.XmlConfigurator.Configure(); 82// log4net.Config.XmlConfigurator.Configure();
@@ -88,15 +88,15 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
88 } 88 }
89 89
90 [Test] 90 [Test]
91 public void RemoveForClient() 91 public void TestRemoveForClient()
92 { 92 {
93 TestHelpers.InMethod(); 93 TestHelpers.InMethod();
94// log4net.Config.XmlConfigurator.Configure(); 94// TestHelpers.EnableLogging();
95 95
96 UUID spId = TestHelpers.ParseTail(0x1); 96 UUID spId = TestHelpers.ParseTail(0x1);
97 97
98 SceneHelpers.AddScenePresence(m_scene, spId); 98 SceneHelpers.AddScenePresence(m_scene, spId);
99 m_scene.IncomingCloseAgent(spId, false); 99 m_scene.CloseAgent(spId, false);
100 100
101 // TODO: Add more assertions for the other aspects of event queues 101 // TODO: Add more assertions for the other aspects of event queues
102 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); 102 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index 6ec1115..7b15284 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -246,8 +246,8 @@ namespace OpenSim.Region.ClientStack.Linden
246 246
247 private Scene m_scene; 247 private Scene m_scene;
248 private MeshCapsDataThrottler m_throttler; 248 private MeshCapsDataThrottler m_throttler;
249 public PollServiceMeshEventArgs(UUID pId, Scene scene) : 249 public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
250 base(null, null, null, null, pId, int.MaxValue) 250 base(null, uri, null, null, null, pId, int.MaxValue)
251 { 251 {
252 m_scene = scene; 252 m_scene = scene;
253 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId); 253 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
@@ -361,7 +361,7 @@ namespace OpenSim.Region.ClientStack.Linden
361 string capUrl = "/CAPS/" + UUID.Random() + "/"; 361 string capUrl = "/CAPS/" + UUID.Random() + "/";
362 362
363 // Register this as a poll service 363 // Register this as a poll service
364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(agentID, m_scene); 364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
365 365
366 args.Type = PollServiceEventArgs.EventType.Mesh; 366 args.Type = PollServiceEventArgs.EventType.Mesh;
367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); 367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index 0570144..e053054 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -84,6 +84,8 @@ namespace OpenSim.Region.ClientStack.Linden
84 84
85 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>(); 85 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
86 86
87 private string m_URL;
88
87 #region ISharedRegionModule Members 89 #region ISharedRegionModule Members
88 90
89 public void Initialise(IConfigSource source) 91 public void Initialise(IConfigSource source)
@@ -215,7 +217,7 @@ namespace OpenSim.Region.ClientStack.Linden
215 private Scene m_scene; 217 private Scene m_scene;
216 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000); 218 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
217 public PollServiceTextureEventArgs(UUID pId, Scene scene) : 219 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
218 base(null, null, null, null, pId, int.MaxValue) 220 base(null, "", null, null, null, pId, int.MaxValue)
219 { 221 {
220 m_scene = scene; 222 m_scene = scene;
221 // x is request id, y is userid 223 // x is request id, y is userid
@@ -368,7 +370,11 @@ namespace OpenSim.Region.ClientStack.Linden
368 port = MainServer.Instance.SSLPort; 370 port = MainServer.Instance.SSLPort;
369 protocol = "https"; 371 protocol = "https";
370 } 372 }
371 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); 373 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
374 if (handler != null)
375 handler.RegisterExternalUserCapsHandler(agentID, caps, "GetTexture", capUrl);
376 else
377 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
372 m_pollservices[agentID] = args; 378 m_pollservices[agentID] = args;
373 m_capsDict[agentID] = capUrl; 379 m_capsDict[agentID] = capUrl;
374 } 380 }
@@ -380,13 +386,11 @@ namespace OpenSim.Region.ClientStack.Linden
380 386
381 private void DeregisterCaps(UUID agentID, Caps caps) 387 private void DeregisterCaps(UUID agentID, Caps caps)
382 { 388 {
383 string capUrl;
384 PollServiceTextureEventArgs args; 389 PollServiceTextureEventArgs args;
385 if (m_capsDict.TryGetValue(agentID, out capUrl)) 390
386 { 391 MainServer.Instance.RemoveHTTPHandler("", m_URL);
387 MainServer.Instance.RemoveHTTPHandler("", capUrl); 392 m_capsDict.Remove(agentID);
388 m_capsDict.Remove(agentID); 393
389 }
390 if (m_pollservices.TryGetValue(agentID, out args)) 394 if (m_pollservices.TryGetValue(agentID, out args))
391 { 395 {
392 m_pollservices.Remove(agentID); 396 m_pollservices.Remove(agentID);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
index 92805e2..94f8bc1 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
@@ -155,6 +155,7 @@ namespace OpenSim.Region.ClientStack.Linden
155 Quaternion rotation = Quaternion.Identity; 155 Quaternion rotation = Quaternion.Identity;
156 Vector3 scale = Vector3.Zero; 156 Vector3 scale = Vector3.Zero;
157 int state = 0; 157 int state = 0;
158 int lastattach = 0;
158 159
159 if (r.Type != OSDType.Map) // not a proper req 160 if (r.Type != OSDType.Map) // not a proper req
160 return responsedata; 161 return responsedata;
@@ -224,6 +225,7 @@ namespace OpenSim.Region.ClientStack.Linden
224 225
225 ray_target_id = ObjMap["RayTargetId"].AsUUID(); 226 ray_target_id = ObjMap["RayTargetId"].AsUUID();
226 state = ObjMap["State"].AsInteger(); 227 state = ObjMap["State"].AsInteger();
228 lastattach = ObjMap["LastAttachPoint"].AsInteger();
227 try 229 try
228 { 230 {
229 ray_end = ((OSDArray)ObjMap["RayEnd"]).AsVector3(); 231 ray_end = ((OSDArray)ObjMap["RayEnd"]).AsVector3();
@@ -290,6 +292,7 @@ namespace OpenSim.Region.ClientStack.Linden
290 292
291 //session_id = rm["session_id"].AsUUID(); 293 //session_id = rm["session_id"].AsUUID();
292 state = rm["state"].AsInteger(); 294 state = rm["state"].AsInteger();
295 lastattach = rm["last_attach_point"].AsInteger();
293 try 296 try
294 { 297 {
295 ray_end = ((OSDArray)rm["ray_end"]).AsVector3(); 298 ray_end = ((OSDArray)rm["ray_end"]).AsVector3();
@@ -331,6 +334,7 @@ namespace OpenSim.Region.ClientStack.Linden
331 pbs.ProfileEnd = (ushort)profile_end; 334 pbs.ProfileEnd = (ushort)profile_end;
332 pbs.Scale = scale; 335 pbs.Scale = scale;
333 pbs.State = (byte)state; 336 pbs.State = (byte)state;
337 pbs.LastAttachPoint = (byte)lastattach;
334 338
335 SceneObjectGroup obj = null; ; 339 SceneObjectGroup obj = null; ;
336 340
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
index 55a503e..769fe28 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
@@ -277,6 +277,7 @@ namespace OpenSim.Region.ClientStack.Linden
277 pbs.ProfileEnd = (ushort) obj.ProfileEnd; 277 pbs.ProfileEnd = (ushort) obj.ProfileEnd;
278 pbs.Scale = obj.Scale; 278 pbs.Scale = obj.Scale;
279 pbs.State = (byte) 0; 279 pbs.State = (byte) 0;
280 pbs.LastAttachPoint = (byte) 0;
280 SceneObjectPart prim = new SceneObjectPart(); 281 SceneObjectPart prim = new SceneObjectPart();
281 prim.UUID = UUID.Random(); 282 prim.UUID = UUID.Random();
282 prim.CreatorID = AgentId; 283 prim.CreatorID = AgentId;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
index 595d01a..112608b 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index 79d56c4..5196368 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -183,7 +183,7 @@ namespace OpenSim.Region.ClientStack.Linden
183 m_isGod = m_scene.Permissions.IsGod(agentID); 183 m_isGod = m_scene.Permissions.IsGod(agentID);
184 } 184 }
185 185
186 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 186 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
187 { 187 {
188 StreamReader reader = new StreamReader(request); 188 StreamReader reader = new StreamReader(request);
189 string message = reader.ReadToEnd(); 189 string message = reader.ReadToEnd();
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
index 7d9f935..e4d8a20 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -68,7 +68,6 @@ namespace OpenSim.Region.ClientStack.Linden
68 /// </summary> 68 /// </summary>
69 private OSDMap m_features = new OSDMap(); 69 private OSDMap m_features = new OSDMap();
70 70
71 private string m_MapImageServerURL = string.Empty;
72 private string m_SearchURL = string.Empty; 71 private string m_SearchURL = string.Empty;
73 private bool m_ExportSupported = false; 72 private bool m_ExportSupported = false;
74 73
@@ -78,15 +77,7 @@ namespace OpenSim.Region.ClientStack.Linden
78 { 77 {
79 IConfig config = source.Configs["SimulatorFeatures"]; 78 IConfig config = source.Configs["SimulatorFeatures"];
80 if (config != null) 79 if (config != null)
81 { 80 {
82 m_MapImageServerURL = config.GetString("MapImageServerURI", string.Empty);
83 if (m_MapImageServerURL != string.Empty)
84 {
85 m_MapImageServerURL = m_MapImageServerURL.Trim();
86 if (!m_MapImageServerURL.EndsWith("/"))
87 m_MapImageServerURL = m_MapImageServerURL + "/";
88 }
89
90 m_SearchURL = config.GetString("SearchServerURI", string.Empty); 81 m_SearchURL = config.GetString("SearchServerURI", string.Empty);
91 82
92 m_ExportSupported = config.GetBoolean("ExportSupported", m_ExportSupported); 83 m_ExportSupported = config.GetBoolean("ExportSupported", m_ExportSupported);
@@ -149,15 +140,16 @@ namespace OpenSim.Region.ClientStack.Linden
149 m_features["PhysicsShapeTypes"] = typesMap; 140 m_features["PhysicsShapeTypes"] = typesMap;
150 141
151 // Extra information for viewers that want to use it 142 // Extra information for viewers that want to use it
152 OSDMap gridServicesMap = new OSDMap(); 143 // TODO: Take these out of here into their respective modules, like map-server-url
153 if (m_MapImageServerURL != string.Empty) 144 OSDMap extrasMap = new OSDMap();
154 gridServicesMap["map-server-url"] = m_MapImageServerURL;
155 if (m_SearchURL != string.Empty) 145 if (m_SearchURL != string.Empty)
156 gridServicesMap["search"] = m_SearchURL; 146 extrasMap["search-server-url"] = m_SearchURL;
157 m_features["GridServices"] = gridServicesMap;
158
159 if (m_ExportSupported) 147 if (m_ExportSupported)
160 m_features["ExportSupported"] = true; 148 extrasMap["ExportSupported"] = true;
149
150 if (extrasMap.Count > 0)
151 m_features["OpenSimExtras"] = extrasMap;
152
161 } 153 }
162 } 154 }
163 155
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index eca576d..47988dd 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -64,11 +64,18 @@ namespace OpenSim.Region.ClientStack.Linden
64 64
65 private Scene m_scene; 65 private Scene m_scene;
66 private bool m_persistBakedTextures; 66 private bool m_persistBakedTextures;
67 private string m_URL;
67 68
68 private IBakedTextureModule m_BakedTextureModule; 69 private IBakedTextureModule m_BakedTextureModule;
69 70
70 public void Initialise(IConfigSource source) 71 public void Initialise(IConfigSource source)
71 { 72 {
73 IConfig config = source.Configs["ClientStack.LindenCaps"];
74 if (config == null)
75 return;
76
77 m_URL = config.GetString("Cap_UploadBakedTexture", string.Empty);
78
72 IConfig appearanceConfig = source.Configs["Appearance"]; 79 IConfig appearanceConfig = source.Configs["Appearance"];
73 if (appearanceConfig != null) 80 if (appearanceConfig != null)
74 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 81 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
@@ -280,23 +287,28 @@ namespace OpenSim.Region.ClientStack.Linden
280 287
281 public void RegisterCaps(UUID agentID, Caps caps) 288 public void RegisterCaps(UUID agentID, Caps caps)
282 { 289 {
283 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler( 290// UUID capID = UUID.Random();
284 caps, m_scene.AssetService, m_persistBakedTextures);
285 291
286 292 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
287 293 if (m_URL == "localhost")
288 caps.RegisterHandler( 294 {
289 "UploadBakedTexture", 295 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler(
290 new RestStreamHandler( 296 caps, m_scene.AssetService, m_persistBakedTextures);
291 "POST",
292 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
293 avatarhandler.UploadBakedTexture,
294 "UploadBakedTexture",
295 agentID.ToString()));
296
297
298
299 297
298 caps.RegisterHandler(
299 "UploadBakedTexture",
300 new RestStreamHandler(
301 "POST",
302 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
303 avatarhandler.UploadBakedTexture,
304 "UploadBakedTexture",
305 agentID.ToString()));
306
307 }
308 else
309 {
310 caps.RegisterHandler("UploadBakedTexture", m_URL);
311 }
300 } 312 }
301 } 313 }
302} \ No newline at end of file 314}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 707cc93..6fc35cd 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -71,9 +71,13 @@ namespace OpenSim.Region.ClientStack.Linden
71 private IInventoryService m_InventoryService; 71 private IInventoryService m_InventoryService;
72 private ILibraryService m_LibraryService; 72 private ILibraryService m_LibraryService;
73 73
74 private bool m_Enabled;
75
76 private string m_fetchInventoryDescendents2Url;
77 private string m_webFetchInventoryDescendentsUrl;
78
74 private static WebFetchInvDescHandler m_webFetchHandler; 79 private static WebFetchInvDescHandler m_webFetchHandler;
75 80
76 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
77 private static Thread[] m_workerThreads = null; 81 private static Thread[] m_workerThreads = null;
78 82
79 private static DoubleQueue<aPollRequest> m_queue = 83 private static DoubleQueue<aPollRequest> m_queue =
@@ -83,22 +87,45 @@ namespace OpenSim.Region.ClientStack.Linden
83 87
84 public void Initialise(IConfigSource source) 88 public void Initialise(IConfigSource source)
85 { 89 {
90 IConfig config = source.Configs["ClientStack.LindenCaps"];
91 if (config == null)
92 return;
93
94 m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty);
95 m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty);
96
97 if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty)
98 {
99 m_Enabled = true;
100 }
86 } 101 }
87 102
88 public void AddRegion(Scene s) 103 public void AddRegion(Scene s)
89 { 104 {
105 if (!m_Enabled)
106 return;
107
90 m_scene = s; 108 m_scene = s;
91 } 109 }
92 110
93 public void RemoveRegion(Scene s) 111 public void RemoveRegion(Scene s)
94 { 112 {
113 if (!m_Enabled)
114 return;
115
95 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 116 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
96 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; 117
118 foreach (Thread t in m_workerThreads)
119 Watchdog.AbortThread(t.ManagedThreadId);
120
97 m_scene = null; 121 m_scene = null;
98 } 122 }
99 123
100 public void RegionLoaded(Scene s) 124 public void RegionLoaded(Scene s)
101 { 125 {
126 if (!m_Enabled)
127 return;
128
102 m_InventoryService = m_scene.InventoryService; 129 m_InventoryService = m_scene.InventoryService;
103 m_LibraryService = m_scene.LibraryService; 130 m_LibraryService = m_scene.LibraryService;
104 131
@@ -106,7 +133,6 @@ namespace OpenSim.Region.ClientStack.Linden
106 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); 133 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
107 134
108 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 135 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
109 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
110 136
111 if (m_workerThreads == null) 137 if (m_workerThreads == null)
112 { 138 {
@@ -140,12 +166,6 @@ namespace OpenSim.Region.ClientStack.Linden
140 166
141 #endregion 167 #endregion
142 168
143 ~WebFetchInvDescModule()
144 {
145 foreach (Thread t in m_workerThreads)
146 Watchdog.AbortThread(t.ManagedThreadId);
147 }
148
149 private class PollServiceInventoryEventArgs : PollServiceEventArgs 169 private class PollServiceInventoryEventArgs : PollServiceEventArgs
150 { 170 {
151 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 171 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -155,8 +175,8 @@ namespace OpenSim.Region.ClientStack.Linden
155 175
156 private Scene m_scene; 176 private Scene m_scene;
157 177
158 public PollServiceInventoryEventArgs(Scene scene, UUID pId) : 178 public PollServiceInventoryEventArgs(Scene scene, string url, UUID pId) :
159 base(null, null, null, null, pId, int.MaxValue) 179 base(null, url, null, null, null, pId, int.MaxValue)
160 { 180 {
161 m_scene = scene; 181 m_scene = scene;
162 182
@@ -278,53 +298,72 @@ namespace OpenSim.Region.ClientStack.Linden
278 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null); 298 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
279 299
280 lock (responses) 300 lock (responses)
281 responses[requestID] = response; 301 responses[requestID] = response;
282 } 302 }
283 } 303 }
284 304
285 private void RegisterCaps(UUID agentID, Caps caps) 305 private void RegisterCaps(UUID agentID, Caps caps)
286 { 306 {
287 string capUrl = "/CAPS/" + UUID.Random() + "/"; 307 RegisterFetchDescendentsCap(agentID, caps, "FetchInventoryDescendents2", m_fetchInventoryDescendents2Url);
288
289 // Register this as a poll service
290 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, agentID);
291
292 args.Type = PollServiceEventArgs.EventType.Inventory;
293 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
294
295 string hostName = m_scene.RegionInfo.ExternalHostName;
296 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
297 string protocol = "http";
298
299 if (MainServer.Instance.UseSSL)
300 {
301 hostName = MainServer.Instance.SSLCommonName;
302 port = MainServer.Instance.SSLPort;
303 protocol = "https";
304 }
305 caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
306
307 m_capsDict[agentID] = capUrl;
308 } 308 }
309 309
310 private void DeregisterCaps(UUID agentID, Caps caps) 310 private void RegisterFetchDescendentsCap(UUID agentID, Caps caps, string capName, string url)
311 { 311 {
312 string capUrl; 312 string capUrl;
313 313
314 if (m_capsDict.TryGetValue(agentID, out capUrl)) 314 // disable the cap clause
315 if (url == "")
316 {
317 return;
318 }
319 // handled by the simulator
320 else if (url == "localhost")
321 {
322 capUrl = "/CAPS/" + UUID.Random() + "/";
323
324 // Register this as a poll service
325 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, capUrl, agentID);
326 args.Type = PollServiceEventArgs.EventType.Inventory;
327
328 caps.RegisterPollHandler(capName, args);
329 }
330 // external handler
331 else
315 { 332 {
316 MainServer.Instance.RemoveHTTPHandler("", capUrl); 333 capUrl = url;
317 m_capsDict.Remove(agentID); 334 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
335 if (handler != null)
336 handler.RegisterExternalUserCapsHandler(agentID,caps,capName,capUrl);
337 else
338 caps.RegisterHandler(capName, capUrl);
318 } 339 }
340
341 // m_log.DebugFormat(
342 // "[FETCH INVENTORY DESCENDENTS2 MODULE]: Registered capability {0} at {1} in region {2} for {3}",
343 // capName, capUrl, m_scene.RegionInfo.RegionName, agentID);
319 } 344 }
320 345
346// private void DeregisterCaps(UUID agentID, Caps caps)
347// {
348// string capUrl;
349//
350// if (m_capsDict.TryGetValue(agentID, out capUrl))
351// {
352// MainServer.Instance.RemoveHTTPHandler("", capUrl);
353// m_capsDict.Remove(agentID);
354// }
355// }
356
321 private void DoInventoryRequests() 357 private void DoInventoryRequests()
322 { 358 {
323 while (true) 359 while (true)
324 { 360 {
361 Watchdog.UpdateThread();
362
325 aPollRequest poolreq = m_queue.Dequeue(); 363 aPollRequest poolreq = m_queue.Dequeue();
326 364
327 poolreq.thepoll.Process(poolreq); 365 if (poolreq != null && poolreq.thepoll != null)
366 poolreq.thepoll.Process(poolreq);
328 } 367 }
329 } 368 }
330 } 369 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
index 3995620..15d6f7f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -424,12 +424,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
424 // foreign user is visiting, we need to try again after the first fail to the local 424 // foreign user is visiting, we need to try again after the first fail to the local
425 // asset service. 425 // asset service.
426 string assetServerURL = string.Empty; 426 string assetServerURL = string.Empty;
427 if (InventoryAccessModule.IsForeignUser(AgentID, out assetServerURL)) 427 if (InventoryAccessModule.IsForeignUser(AgentID, out assetServerURL) && !string.IsNullOrEmpty(assetServerURL))
428 { 428 {
429 if (!assetServerURL.EndsWith("/") && !assetServerURL.EndsWith("=")) 429 if (!assetServerURL.EndsWith("/") && !assetServerURL.EndsWith("="))
430 assetServerURL = assetServerURL + "/"; 430 assetServerURL = assetServerURL + "/";
431 431
432 m_log.DebugFormat("[J2KIMAGE]: texture {0} not found in local asset storage. Trying user's storage.", assetServerURL + id); 432// m_log.DebugFormat("[J2KIMAGE]: texture {0} not found in local asset storage. Trying user's storage.", assetServerURL + id);
433 AssetService.Get(assetServerURL + id, InventoryAccessModule, AssetReceived); 433 AssetService.Get(assetServerURL + id, InventoryAccessModule, AssetReceived);
434 return; 434 return;
435 } 435 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 7c62f90..f599342 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -84,6 +84,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
84 public event ModifyTerrain OnModifyTerrain; 84 public event ModifyTerrain OnModifyTerrain;
85 public event Action<IClientAPI> OnRegionHandShakeReply; 85 public event Action<IClientAPI> OnRegionHandShakeReply;
86 public event GenericCall1 OnRequestWearables; 86 public event GenericCall1 OnRequestWearables;
87 public event CachedTextureRequest OnCachedTextureRequest;
87 public event SetAppearance OnSetAppearance; 88 public event SetAppearance OnSetAppearance;
88 public event AvatarNowWearing OnAvatarNowWearing; 89 public event AvatarNowWearing OnAvatarNowWearing;
89 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; 90 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
@@ -95,6 +96,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
95 public event Action<IClientAPI, bool> OnCompleteMovementToRegion; 96 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
96 public event UpdateAgent OnPreAgentUpdate; 97 public event UpdateAgent OnPreAgentUpdate;
97 public event UpdateAgent OnAgentUpdate; 98 public event UpdateAgent OnAgentUpdate;
99 public event UpdateAgent OnAgentCameraUpdate;
98 public event AgentRequestSit OnAgentRequestSit; 100 public event AgentRequestSit OnAgentRequestSit;
99 public event AgentSit OnAgentSit; 101 public event AgentSit OnAgentSit;
100 public event AvatarPickerRequest OnAvatarPickerRequest; 102 public event AvatarPickerRequest OnAvatarPickerRequest;
@@ -335,6 +337,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
335 private bool m_VelocityInterpolate = false; 337 private bool m_VelocityInterpolate = false;
336 private const uint MaxTransferBytesPerPacket = 600; 338 private const uint MaxTransferBytesPerPacket = 600;
337 339
340 private volatile bool m_justEditedTerrain = false;
338 341
339 /// <value> 342 /// <value>
340 /// List used in construction of data blocks for an object update packet. This is to stop us having to 343 /// List used in construction of data blocks for an object update packet. This is to stop us having to
@@ -367,7 +370,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
367 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods 370 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
368 /// cannot retain a reference to it outside of that method. 371 /// cannot retain a reference to it outside of that method.
369 /// </remarks> 372 /// </remarks>
370 private AgentUpdateArgs m_lastAgentUpdateArgs; 373 private AgentUpdateArgs m_thisAgentUpdateArgs = new AgentUpdateArgs();
371 374
372 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 375 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
373 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 376 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -504,6 +507,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
504 m_udpServer = udpServer; 507 m_udpServer = udpServer;
505 m_udpClient = udpClient; 508 m_udpClient = udpClient;
506 m_udpClient.OnQueueEmpty += HandleQueueEmpty; 509 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
510 m_udpClient.HasUpdates += HandleHasUpdates;
507 m_udpClient.OnPacketStats += PopulateStats; 511 m_udpClient.OnPacketStats += PopulateStats;
508 512
509 m_prioritizer = new Prioritizer(m_scene); 513 m_prioritizer = new Prioritizer(m_scene);
@@ -533,7 +537,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
533 // We still perform a force close inside the sync lock since this is intended to attempt close where 537 // We still perform a force close inside the sync lock since this is intended to attempt close where
534 // there is some unidentified connection problem, not where we have issues due to deadlock 538 // there is some unidentified connection problem, not where we have issues due to deadlock
535 if (!IsActive && !force) 539 if (!IsActive && !force)
540 {
541 m_log.DebugFormat(
542 "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set",
543 Name, m_scene.Name);
544
536 return; 545 return;
546 }
537 547
538 IsActive = false; 548 IsActive = false;
539 CloseWithoutChecks(sendStop); 549 CloseWithoutChecks(sendStop);
@@ -709,12 +719,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
709 //there is a local handler for this packet type 719 //there is a local handler for this packet type
710 if (pprocessor.Async) 720 if (pprocessor.Async)
711 { 721 {
722 ClientInfo cinfo = UDPClient.GetClientInfo();
723 if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString()))
724 cinfo.AsyncRequests[packet.Type.ToString()] = 0;
725 cinfo.AsyncRequests[packet.Type.ToString()]++;
726
712 object obj = new AsyncPacketProcess(this, pprocessor.method, packet); 727 object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
713 Util.FireAndForget(ProcessSpecificPacketAsync, obj); 728 Util.FireAndForget(ProcessSpecificPacketAsync, obj);
714 result = true; 729 result = true;
715 } 730 }
716 else 731 else
717 { 732 {
733 ClientInfo cinfo = UDPClient.GetClientInfo();
734 if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString()))
735 cinfo.SyncRequests[packet.Type.ToString()] = 0;
736 cinfo.SyncRequests[packet.Type.ToString()]++;
737
718 result = pprocessor.method(this, packet); 738 result = pprocessor.method(this, packet);
719 } 739 }
720 } 740 }
@@ -729,6 +749,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
729 } 749 }
730 if (found) 750 if (found)
731 { 751 {
752 ClientInfo cinfo = UDPClient.GetClientInfo();
753 if (!cinfo.GenericRequests.ContainsKey(packet.Type.ToString()))
754 cinfo.GenericRequests[packet.Type.ToString()] = 0;
755 cinfo.GenericRequests[packet.Type.ToString()]++;
756
732 result = method(this, packet); 757 result = method(this, packet);
733 } 758 }
734 } 759 }
@@ -758,7 +783,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
758 783
759 public virtual void Start() 784 public virtual void Start()
760 { 785 {
761 m_scene.AddNewClient(this, PresenceType.User); 786 m_scene.AddNewAgent(this, PresenceType.User);
762 787
763 RefreshGroupMembership(); 788 RefreshGroupMembership();
764 } 789 }
@@ -820,12 +845,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
820 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); 845 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
821 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; 846 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
822 847
823 handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[0]; 848 handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[1];
824// OutPacket(handshake, ThrottleOutPacketType.Task); 849 handshake.RegionInfo4[0] = new RegionHandshakePacket.RegionInfo4Block();
825 // use same as MoveAgentIntoRegion (both should be task ) 850 handshake.RegionInfo4[0].RegionFlagsExtended = args.regionFlags;
851 handshake.RegionInfo4[0].RegionProtocols = 0; // 1 here would indicate that SSB is supported
852
826 OutPacket(handshake, ThrottleOutPacketType.Unknown); 853 OutPacket(handshake, ThrottleOutPacketType.Unknown);
827 } 854 }
828 855
856
829 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 857 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
830 { 858 {
831 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); 859 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
@@ -1210,9 +1238,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1210 LLHeightFieldMoronize(map); 1238 LLHeightFieldMoronize(map);
1211 1239
1212 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1240 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1213 layerpack.Header.Reliable = true; 1241
1242 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
1243 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
1244 // We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area
1245 // invalidating previous packets for that area.
1246
1247 // It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a
1248 // tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower.
1249
1250 // One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will
1251 // have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain
1252 // patches.
1214 1253
1215 OutPacket(layerpack, ThrottleOutPacketType.Task); 1254 // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss.
1255 if (m_justEditedTerrain)
1256 {
1257 layerpack.Header.Reliable = false;
1258 OutPacket(layerpack,
1259 ThrottleOutPacketType.Unknown );
1260 }
1261 else
1262 {
1263 layerpack.Header.Reliable = true;
1264 OutPacket(layerpack,
1265 ThrottleOutPacketType.Task);
1266 }
1216 } 1267 }
1217 catch (Exception e) 1268 catch (Exception e)
1218 { 1269 {
@@ -1405,6 +1456,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1405 1456
1406 mapReply.AgentData.AgentID = AgentId; 1457 mapReply.AgentData.AgentID = AgentId;
1407 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length]; 1458 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length];
1459 mapReply.Size = new MapBlockReplyPacket.SizeBlock[mapBlocks2.Length];
1408 mapReply.AgentData.Flags = flag; 1460 mapReply.AgentData.Flags = flag;
1409 1461
1410 for (int i = 0; i < mapBlocks2.Length; i++) 1462 for (int i = 0; i < mapBlocks2.Length; i++)
@@ -1419,6 +1471,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1419 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags; 1471 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags;
1420 mapReply.Data[i].Access = mapBlocks2[i].Access; 1472 mapReply.Data[i].Access = mapBlocks2[i].Access;
1421 mapReply.Data[i].Agents = mapBlocks2[i].Agents; 1473 mapReply.Data[i].Agents = mapBlocks2[i].Agents;
1474
1475 // TODO: hookup varregion sim size here
1476 mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock();
1477 mapReply.Size[i].SizeX = 256;
1478 mapReply.Size[i].SizeY = 256;
1422 } 1479 }
1423 OutPacket(mapReply, ThrottleOutPacketType.Land); 1480 OutPacket(mapReply, ThrottleOutPacketType.Land);
1424 } 1481 }
@@ -1580,7 +1637,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1580 OutPacket(pc, ThrottleOutPacketType.Unknown); 1637 OutPacket(pc, ThrottleOutPacketType.Unknown);
1581 } 1638 }
1582 1639
1583 public void SendKillObject(ulong regionHandle, List<uint> localIDs) 1640 public void SendKillObject(List<uint> localIDs)
1584 { 1641 {
1585// foreach (uint id in localIDs) 1642// foreach (uint id in localIDs)
1586// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); 1643// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
@@ -2594,11 +2651,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2594 { 2651 {
2595 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); 2652 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
2596 avatarSitResponse.SitObject.ID = TargetID; 2653 avatarSitResponse.SitObject.ID = TargetID;
2597 if (CameraAtOffset != Vector3.Zero) 2654 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2598 { 2655 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2599 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2600 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2601 }
2602 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; 2656 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook;
2603 avatarSitResponse.SitTransform.AutoPilot = autopilot; 2657 avatarSitResponse.SitTransform.AutoPilot = autopilot;
2604 avatarSitResponse.SitTransform.SitPosition = OffsetPos; 2658 avatarSitResponse.SitTransform.SitPosition = OffsetPos;
@@ -3794,12 +3848,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3794 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); 3848 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
3795 3849
3796 // Count this as a resent packet since we are going to requeue all of the updates contained in it 3850 // Count this as a resent packet since we are going to requeue all of the updates contained in it
3797 Interlocked.Increment(ref m_udpClient.PacketsResent); 3851 Interlocked.Increment(ref m_udpClient.PacketsResent);
3852
3853 // We're not going to worry about interlock yet since its not currently critical that this total count
3854 // is 100% correct
3855 m_udpServer.PacketsResentCount++;
3798 3856
3799 foreach (EntityUpdate update in updates) 3857 foreach (EntityUpdate update in updates)
3800 ResendPrimUpdate(update); 3858 ResendPrimUpdate(update);
3801 } 3859 }
3802 3860
3861// OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3862// OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3863// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3864// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3865//
3866// OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3867// OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3868// OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3869// OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3870
3871
3803 private void ProcessEntityUpdates(int maxUpdates) 3872 private void ProcessEntityUpdates(int maxUpdates)
3804 { 3873 {
3805 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3874 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3812,6 +3881,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3812 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 3881 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3813 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 3882 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3814 3883
3884// objectUpdateBlocks.Value.Clear();
3885// compressedUpdateBlocks.Value.Clear();
3886// terseUpdateBlocks.Value.Clear();
3887// terseAgentUpdateBlocks.Value.Clear();
3888// objectUpdates.Value.Clear();
3889// compressedUpdates.Value.Clear();
3890// terseUpdates.Value.Clear();
3891// terseAgentUpdates.Value.Clear();
3892
3815 // Check to see if this is a flush 3893 // Check to see if this is a flush
3816 if (maxUpdates <= 0) 3894 if (maxUpdates <= 0)
3817 { 3895 {
@@ -4140,8 +4218,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4140 4218
4141 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) 4219 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
4142 { 4220 {
4221// if (!m_udpServer.IsRunningOutbound)
4222// return;
4223
4143 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) 4224 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
4144 { 4225 {
4226// if (!m_udpServer.IsRunningOutbound)
4227// return;
4228
4145 if (m_maxUpdates == 0 || m_LastQueueFill == 0) 4229 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
4146 { 4230 {
4147 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback; 4231 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
@@ -4167,6 +4251,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4167 ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); 4251 ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
4168 } 4252 }
4169 4253
4254 internal bool HandleHasUpdates(ThrottleOutPacketTypeFlags categories)
4255 {
4256 bool hasUpdates = false;
4257
4258 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
4259 {
4260 if (m_entityUpdates.Count > 0)
4261 hasUpdates = true;
4262 else if (m_entityProps.Count > 0)
4263 hasUpdates = true;
4264 }
4265
4266 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
4267 {
4268 if (ImageManager.HasUpdates())
4269 hasUpdates = true;
4270 }
4271
4272 return hasUpdates;
4273 }
4274
4170 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) 4275 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
4171 { 4276 {
4172 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); 4277 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
@@ -4312,6 +4417,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4312 // Count this as a resent packet since we are going to requeue all of the updates contained in it 4417 // Count this as a resent packet since we are going to requeue all of the updates contained in it
4313 Interlocked.Increment(ref m_udpClient.PacketsResent); 4418 Interlocked.Increment(ref m_udpClient.PacketsResent);
4314 4419
4420 // We're not going to worry about interlock yet since its not currently critical that this total count
4421 // is 100% correct
4422 m_udpServer.PacketsResentCount++;
4423
4315 foreach (ObjectPropertyUpdate update in updates) 4424 foreach (ObjectPropertyUpdate update in updates)
4316 ResendPropertyUpdate(update); 4425 ResendPropertyUpdate(update);
4317 } 4426 }
@@ -4499,6 +4608,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4499 SceneObjectPart root = sop.ParentGroup.RootPart; 4608 SceneObjectPart root = sop.ParentGroup.RootPart;
4500 4609
4501 block.TouchName = Util.StringToBytes256(root.TouchName); 4610 block.TouchName = Util.StringToBytes256(root.TouchName);
4611
4612 // SL 3.3.4, at least, appears to read this information as a concatenated byte[] stream of UUIDs but
4613 // it's not yet clear whether this is actually used. If this is done in the future then a pre-cached
4614 // copy is really needed since it's less efficient to be constantly recreating this byte array.
4615// using (MemoryStream memStream = new MemoryStream())
4616// {
4617// using (BinaryWriter binWriter = new BinaryWriter(memStream))
4618// {
4619// for (int i = 0; i < sop.GetNumberOfSides(); i++)
4620// {
4621// Primitive.TextureEntryFace teFace = sop.Shape.Textures.FaceTextures[i];
4622//
4623// UUID textureID;
4624//
4625// if (teFace != null)
4626// textureID = teFace.TextureID;
4627// else
4628// textureID = sop.Shape.Textures.DefaultTexture.TextureID;
4629//
4630// binWriter.Write(textureID.GetBytes());
4631// }
4632//
4633// block.TextureID = memStream.ToArray();
4634// }
4635// }
4636
4502 block.TextureID = new byte[0]; // TextureID ??? 4637 block.TextureID = new byte[0]; // TextureID ???
4503 block.SitName = Util.StringToBytes256(root.SitName); 4638 block.SitName = Util.StringToBytes256(root.SitName);
4504 block.OwnerMask = root.OwnerMask; 4639 block.OwnerMask = root.OwnerMask;
@@ -4877,7 +5012,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4877 5012
4878 public void SendForceClientSelectObjects(List<uint> ObjectIDs) 5013 public void SendForceClientSelectObjects(List<uint> ObjectIDs)
4879 { 5014 {
4880 m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count); 5015// m_log.DebugFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count);
4881 5016
4882 bool firstCall = true; 5017 bool firstCall = true;
4883 const int MAX_OBJECTS_PER_PACKET = 251; 5018 const int MAX_OBJECTS_PER_PACKET = 251;
@@ -5015,15 +5150,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5015 } 5150 }
5016 5151
5017 attachPoint = 0; 5152 attachPoint = 0;
5153// m_log.DebugFormat(
5154// "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
5155
5156 // attachPoint = presence.State; // Core: commented
5018 collisionPlane = presence.CollisionPlane; 5157 collisionPlane = presence.CollisionPlane;
5019 velocity = presence.Velocity; 5158 velocity = presence.Velocity;
5020 acceleration = Vector3.Zero; 5159 acceleration = Vector3.Zero;
5021 5160
5022 // Interestingly, sending this to non-zero will cause the client's avatar to start moving & accelerating
5023 // in that direction, even though we don't model this on the server. Implementing this in the future
5024 // may improve movement smoothness.
5025// acceleration = new Vector3(1, 0, 0);
5026
5027 if (sendTexture) 5161 if (sendTexture)
5028 textureEntry = presence.Appearance.Texture.GetBytes(); 5162 textureEntry = presence.Appearance.Texture.GetBytes();
5029 else 5163 else
@@ -5034,7 +5168,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5034 SceneObjectPart part = (SceneObjectPart)entity; 5168 SceneObjectPart part = (SceneObjectPart)entity;
5035 5169
5036 attachPoint = part.ParentGroup.AttachmentPoint; 5170 attachPoint = part.ParentGroup.AttachmentPoint;
5037 5171 attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16));
5038// m_log.DebugFormat( 5172// m_log.DebugFormat(
5039// "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", 5173// "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}",
5040// attachPoint, part.Name, part.LocalId, Name); 5174// attachPoint, part.Name, part.LocalId, Name);
@@ -5062,7 +5196,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5062 pos += 4; 5196 pos += 4;
5063 5197
5064 // Avatar/CollisionPlane 5198 // Avatar/CollisionPlane
5065 data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ; 5199 data[pos++] = (byte) attachPoint;
5066 if (avatar) 5200 if (avatar)
5067 { 5201 {
5068 data[pos++] = 1; 5202 data[pos++] = 1;
@@ -5143,6 +5277,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5143 parentID = part.ParentGroup.RootPart.LocalId; 5277 parentID = part.ParentGroup.RootPart.LocalId;
5144 } 5278 }
5145 } 5279 }
5280// m_log.DebugFormat(
5281// "[LLCLIENTVIEW]: Sending full update to {0} with position {1} in {2}", Name, data.OffsetPosition, m_scene.Name);
5146 5282
5147 byte[] objectData = new byte[76]; 5283 byte[] objectData = new byte[76];
5148 5284
@@ -5168,7 +5304,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5168 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + 5304 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
5169 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); 5305 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
5170 update.ObjectData = objectData; 5306 update.ObjectData = objectData;
5171 update.ParentID = parentID; 5307
5308 SceneObjectPart parentPart = data.ParentPart;
5309 if (parentPart != null)
5310 update.ParentID = parentPart.ParentGroup.LocalId;
5311 else
5312 update.ParentID = 0;
5313
5172 update.PathCurve = 16; 5314 update.PathCurve = 16;
5173 update.PathScaleX = 100; 5315 update.PathScaleX = 100;
5174 update.PathScaleY = 100; 5316 update.PathScaleY = 100;
@@ -5387,7 +5529,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5387 AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject); 5529 AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject);
5388 AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject); 5530 AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject);
5389 AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand); 5531 AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand);
5390 AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply); 5532 AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply, false);
5391 AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest); 5533 AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest);
5392 AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance); 5534 AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance);
5393 AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing); 5535 AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing);
@@ -5448,8 +5590,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5448 AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false); 5590 AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false);
5449 AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false); 5591 AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false);
5450 AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false); 5592 AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false);
5451 AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage); 5593 AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage, false);
5452 AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest); 5594 AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest, false);
5453 AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest); 5595 AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest);
5454 AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer); 5596 AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer);
5455 AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket); 5597 AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket);
@@ -5481,7 +5623,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5481 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); 5623 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel);
5482 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); 5624 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest);
5483 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false); 5625 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false);
5484 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest); 5626 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest, false);
5485 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest); 5627 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest);
5486 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false); 5628 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false);
5487 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false); 5629 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false);
@@ -5594,83 +5736,137 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5594 5736
5595 #region Packet Handlers 5737 #region Packet Handlers
5596 5738
5739 public int TotalAgentUpdates { get; set; }
5740
5597 #region Scene/Avatar 5741 #region Scene/Avatar
5598 5742
5599 private bool HandleAgentUpdate(IClientAPI sener, Packet packet) 5743 // Threshold for body rotation to be a significant agent update
5744 private const float QDELTA = 0.000001f;
5745 // Threshold for camera rotation to be a significant agent update
5746 private const float VDELTA = 0.01f;
5747
5748 /// <summary>
5749 /// This checks the update significance against the last update made.
5750 /// </summary>
5751 /// <remarks>Can only be called by one thread at a time</remarks>
5752 /// <returns></returns>
5753 /// <param name='x'></param>
5754 public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5600 { 5755 {
5601 if (OnAgentUpdate != null) 5756 return CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x);
5602 { 5757 }
5603 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5604 5758
5605 #region Packet Session and User Check 5759 /// <summary>
5606 if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) 5760 /// This checks the movement/state update significance against the last update made.
5607 { 5761 /// </summary>
5608 PacketPool.Instance.ReturnPacket(packet); 5762 /// <remarks>Can only be called by one thread at a time</remarks>
5609 return false; 5763 /// <returns></returns>
5610 } 5764 /// <param name='x'></param>
5611 #endregion 5765 private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5766 {
5767 float qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2);
5768 //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2);
5769
5770 bool movementSignificant =
5771 (qdelta1 > QDELTA) // significant if body rotation above threshold
5772 // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack
5773 // || (qdelta2 > QDELTA * 10) // significant if head rotation above threshold
5774 || (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
5775 || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands
5776 || (x.Far != m_thisAgentUpdateArgs.Far) // significant if far distance changed
5777 || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed
5778 || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed
5779 ;
5780 //if (movementSignificant)
5781 //{
5782 //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}",
5783 // qdelta1, qdelta2);
5784 //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3}",
5785 // x.ControlFlags, x.Flags, x.Far, x.State);
5786 //}
5787 return movementSignificant;
5788 }
5612 5789
5613 bool update = false; 5790 /// <summary>
5614 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; 5791 /// This checks the camera update significance against the last update made.
5615 5792 /// </summary>
5616 if (m_lastAgentUpdateArgs != null) 5793 /// <remarks>Can only be called by one thread at a time</remarks>
5617 { 5794 /// <returns></returns>
5618 // These should be ordered from most-likely to 5795 /// <param name='x'></param>
5619 // least likely to change. I've made an initial 5796 private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5620 // guess at that. 5797 {
5621 update = 5798 float vdelta1 = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis);
5622 ( 5799 float vdelta2 = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter);
5623 (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || 5800 float vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis);
5624 (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || 5801 float vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis);
5625 (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) ||
5626 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5627 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5628 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5629 (x.ControlFlags != 0) ||
5630 (x.Far != m_lastAgentUpdateArgs.Far) ||
5631 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5632 (x.State != m_lastAgentUpdateArgs.State) ||
5633 (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) ||
5634 (x.SessionID != m_lastAgentUpdateArgs.SessionID) ||
5635 (x.AgentID != m_lastAgentUpdateArgs.AgentID)
5636 );
5637 }
5638 else
5639 {
5640 m_lastAgentUpdateArgs = new AgentUpdateArgs();
5641 update = true;
5642 }
5643 5802
5644 if (update) 5803 bool cameraSignificant =
5645 { 5804 (vdelta1 > VDELTA) ||
5646// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); 5805 (vdelta2 > VDELTA) ||
5806 (vdelta3 > VDELTA) ||
5807 (vdelta4 > VDELTA)
5808 ;
5647 5809
5648 m_lastAgentUpdateArgs.AgentID = x.AgentID; 5810 //if (cameraSignificant)
5649 m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; 5811 //{
5650 m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; 5812 //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}",
5651 m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; 5813 // x.CameraAtAxis, x.CameraCenter);
5652 m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; 5814 //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}",
5653 m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; 5815 // x.CameraLeftAxis, x.CameraUpAxis);
5654 m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; 5816 //}
5655 m_lastAgentUpdateArgs.Far = x.Far;
5656 m_lastAgentUpdateArgs.Flags = x.Flags;
5657 m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation;
5658 m_lastAgentUpdateArgs.SessionID = x.SessionID;
5659 m_lastAgentUpdateArgs.State = x.State;
5660 5817
5661 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 5818 return cameraSignificant;
5662 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; 5819 }
5663 5820
5664 if (handlerPreAgentUpdate != null) 5821 private bool HandleAgentUpdate(IClientAPI sener, Packet packet)
5665 OnPreAgentUpdate(this, m_lastAgentUpdateArgs); 5822 {
5823 // We got here, which means that something in agent update was significant
5666 5824
5667 if (handlerAgentUpdate != null) 5825 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5668 OnAgentUpdate(this, m_lastAgentUpdateArgs); 5826 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5669 5827
5670 handlerAgentUpdate = null; 5828 if (x.AgentID != AgentId || x.SessionID != SessionId)
5671 handlerPreAgentUpdate = null; 5829 return false;
5672 } 5830
5673 } 5831 // Before we update the current m_thisAgentUpdateArgs, let's check this again
5832 // to see what exactly changed
5833 bool movement = CheckAgentMovementUpdateSignificance(x);
5834 bool camera = CheckAgentCameraUpdateSignificance(x);
5835
5836 m_thisAgentUpdateArgs.AgentID = x.AgentID;
5837 m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
5838 m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5839 m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
5840 m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5841 m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5842 m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
5843 m_thisAgentUpdateArgs.Far = x.Far;
5844 m_thisAgentUpdateArgs.Flags = x.Flags;
5845 m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
5846 m_thisAgentUpdateArgs.SessionID = x.SessionID;
5847 m_thisAgentUpdateArgs.State = x.State;
5848
5849 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5850 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5851 UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate;
5852
5853 // Was there a significant movement/state change?
5854 if (movement)
5855 {
5856 if (handlerPreAgentUpdate != null)
5857 OnPreAgentUpdate(this, m_thisAgentUpdateArgs);
5858
5859 if (handlerAgentUpdate != null)
5860 OnAgentUpdate(this, m_thisAgentUpdateArgs);
5861 }
5862 // Was there a significant camera(s) change?
5863 if (camera)
5864 if (handlerAgentCameraUpdate != null)
5865 handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs);
5866
5867 handlerAgentUpdate = null;
5868 handlerPreAgentUpdate = null;
5869 handlerAgentCameraUpdate = null;
5674 5870
5675 PacketPool.Instance.ReturnPacket(packet); 5871 PacketPool.Instance.ReturnPacket(packet);
5676 5872
@@ -6260,6 +6456,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6260 //m_log.Info("[LAND]: LAND:" + modify.ToString()); 6456 //m_log.Info("[LAND]: LAND:" + modify.ToString());
6261 if (modify.ParcelData.Length > 0) 6457 if (modify.ParcelData.Length > 0)
6262 { 6458 {
6459 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore,
6460 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit.
6461 m_justEditedTerrain = true; // Prevent terrain packet (Land layer) from being queued, make it unreliable
6263 if (OnModifyTerrain != null) 6462 if (OnModifyTerrain != null)
6264 { 6463 {
6265 for (int i = 0; i < modify.ParcelData.Length; i++) 6464 for (int i = 0; i < modify.ParcelData.Length; i++)
@@ -6275,6 +6474,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6275 } 6474 }
6276 } 6475 }
6277 } 6476 }
6477 m_justEditedTerrain = false; // Queue terrain packet (Land layer) if necessary, make it reliable again
6278 } 6478 }
6279 6479
6280 return true; 6480 return true;
@@ -6636,6 +6836,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6636 } 6836 }
6637 #endregion 6837 #endregion
6638 6838
6839 if (SceneAgent.IsChildAgent)
6840 {
6841 SendCantSitBecauseChildAgentResponse();
6842 return true;
6843 }
6844
6639 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; 6845 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
6640 6846
6641 if (handlerAgentRequestSit != null) 6847 if (handlerAgentRequestSit != null)
@@ -6660,6 +6866,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6660 } 6866 }
6661 #endregion 6867 #endregion
6662 6868
6869 if (SceneAgent.IsChildAgent)
6870 {
6871 SendCantSitBecauseChildAgentResponse();
6872 return true;
6873 }
6874
6663 AgentSit handlerAgentSit = OnAgentSit; 6875 AgentSit handlerAgentSit = OnAgentSit;
6664 if (handlerAgentSit != null) 6876 if (handlerAgentSit != null)
6665 { 6877 {
@@ -6669,6 +6881,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6669 return true; 6881 return true;
6670 } 6882 }
6671 6883
6884 /// <summary>
6885 /// Used when a child agent gets a sit response which should not be fulfilled.
6886 /// </summary>
6887 private void SendCantSitBecauseChildAgentResponse()
6888 {
6889 SendAlertMessage("Try moving closer. Can't sit on object because it is not in the same region as you.");
6890 }
6891
6672 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack) 6892 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack)
6673 { 6893 {
6674 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; 6894 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack;
@@ -7879,129 +8099,145 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7879 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); 8099 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
7880 8100
7881 TransferRequestPacket transfer = (TransferRequestPacket)Pack; 8101 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
7882 //m_log.Debug("Transfer Request: " + transfer.ToString());
7883 // Validate inventory transfers
7884 // Has to be done here, because AssetCache can't do it
7885 //
7886 UUID taskID = UUID.Zero; 8102 UUID taskID = UUID.Zero;
7887 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) 8103 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
7888 { 8104 {
7889 taskID = new UUID(transfer.TransferInfo.Params, 48);
7890 UUID itemID = new UUID(transfer.TransferInfo.Params, 64);
7891 UUID requestID = new UUID(transfer.TransferInfo.Params, 80);
7892
7893// m_log.DebugFormat(
7894// "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
7895// requestID, itemID, taskID, Name);
7896
7897 if (!(((Scene)m_scene).Permissions.BypassPermissions())) 8105 if (!(((Scene)m_scene).Permissions.BypassPermissions()))
7898 { 8106 {
7899 if (taskID != UUID.Zero) // Prim 8107 // We're spawning a thread because the permissions check can block this thread
8108 Util.FireAndForget(delegate
7900 { 8109 {
7901 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); 8110 // This requests the asset if needed
8111 HandleSimInventoryTransferRequestWithPermsCheck(sender, transfer);
8112 });
8113 return true;
8114 }
8115 }
8116 else if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate)
8117 {
8118 //TransferRequestPacket does not include covenant uuid?
8119 //get scene covenant uuid
8120 taskID = m_scene.RegionInfo.RegionSettings.Covenant;
8121 }
7902 8122
7903 if (part == null) 8123 // This is non-blocking
7904 { 8124 MakeAssetRequest(transfer, taskID);
7905 m_log.WarnFormat(
7906 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
7907 Name, requestID, itemID, taskID);
7908 return true;
7909 }
7910 8125
7911 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID); 8126 return true;
7912 if (tii == null) 8127 }
7913 {
7914 m_log.WarnFormat(
7915 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
7916 Name, requestID, itemID, taskID);
7917 return true;
7918 }
7919 8128
7920 if (tii.Type == (int)AssetType.LSLText) 8129 private void HandleSimInventoryTransferRequestWithPermsCheck(IClientAPI sender, TransferRequestPacket transfer)
7921 { 8130 {
7922 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId)) 8131 UUID taskID = new UUID(transfer.TransferInfo.Params, 48);
7923 return true; 8132 UUID itemID = new UUID(transfer.TransferInfo.Params, 64);
7924 } 8133 UUID requestID = new UUID(transfer.TransferInfo.Params, 80);
7925 else if (tii.Type == (int)AssetType.Notecard)
7926 {
7927 if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId))
7928 return true;
7929 }
7930 else
7931 {
7932 // TODO: Change this code to allow items other than notecards and scripts to be successfully
7933 // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
7934 if (part.OwnerID != AgentId)
7935 {
7936 m_log.WarnFormat(
7937 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
7938 Name, requestID, itemID, taskID, part.OwnerID);
7939 return true;
7940 }
7941 8134
7942 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) 8135 //m_log.DebugFormat(
7943 { 8136 // "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
7944 m_log.WarnFormat( 8137 // requestID, itemID, taskID, Name);
7945 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
7946 Name, requestID, itemID, taskID);
7947 return true;
7948 }
7949 8138
7950 if (tii.OwnerID != AgentId) 8139 //m_log.Debug("Transfer Request: " + transfer.ToString());
7951 { 8140 // Validate inventory transfers
7952 m_log.WarnFormat( 8141 // Has to be done here, because AssetCache can't do it
7953 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}", 8142 //
7954 Name, requestID, itemID, taskID, tii.OwnerID); 8143 if (taskID != UUID.Zero) // Prim
7955 return true; 8144 {
7956 } 8145 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID);
7957 8146
7958 if (( 8147 if (part == null)
7959 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) 8148 {
7960 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) 8149 m_log.WarnFormat(
7961 { 8150 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
7962 m_log.WarnFormat( 8151 Name, requestID, itemID, taskID);
7963 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer", 8152 return;
7964 Name, requestID, itemID, taskID); 8153 }
7965 return true;
7966 }
7967 8154
7968 if (tii.AssetID != requestID) 8155 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID);
7969 { 8156 if (tii == null)
7970 m_log.WarnFormat( 8157 {
7971 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}", 8158 m_log.WarnFormat(
7972 Name, requestID, itemID, taskID, tii.AssetID); 8159 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
7973 return true; 8160 Name, requestID, itemID, taskID);
7974 } 8161 return;
7975 } 8162 }
8163
8164 if (tii.Type == (int)AssetType.LSLText)
8165 {
8166 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId))
8167 return;
8168 }
8169 else if (tii.Type == (int)AssetType.Notecard)
8170 {
8171 if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId))
8172 return;
8173 }
8174 else
8175 {
8176 // TODO: Change this code to allow items other than notecards and scripts to be successfully
8177 // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
8178 if (part.OwnerID != AgentId)
8179 {
8180 m_log.WarnFormat(
8181 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
8182 Name, requestID, itemID, taskID, part.OwnerID);
8183 return;
7976 } 8184 }
7977 else // Agent 8185
8186 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
7978 { 8187 {
7979 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 8188 m_log.WarnFormat(
7980 if (invAccess != null) 8189 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
7981 { 8190 Name, requestID, itemID, taskID);
7982 if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID)) 8191 return;
7983 return false; 8192 }
7984 } 8193
7985 else 8194 if (tii.OwnerID != AgentId)
7986 { 8195 {
7987 return false; 8196 m_log.WarnFormat(
7988 } 8197 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}",
8198 Name, requestID, itemID, taskID, tii.OwnerID);
8199 return;
8200 }
8201
8202 if ((
8203 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
8204 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
8205 {
8206 m_log.WarnFormat(
8207 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer",
8208 Name, requestID, itemID, taskID);
8209 return;
8210 }
8211
8212 if (tii.AssetID != requestID)
8213 {
8214 m_log.WarnFormat(
8215 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}",
8216 Name, requestID, itemID, taskID, tii.AssetID);
8217 return;
7989 } 8218 }
7990 } 8219 }
7991 } 8220 }
7992 else 8221 else // Agent
7993 if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate) 8222 {
8223 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
8224 if (invAccess != null)
7994 { 8225 {
7995 //TransferRequestPacket does not include covenant uuid? 8226 if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID))
7996 //get scene covenant uuid 8227 return;
7997 taskID = m_scene.RegionInfo.RegionSettings.Covenant;
7998 } 8228 }
8229 else
8230 {
8231 return;
8232 }
8233 }
7999 8234
8235 // Permissions out of the way, let's request the asset
8000 MakeAssetRequest(transfer, taskID); 8236 MakeAssetRequest(transfer, taskID);
8001 8237
8002 return true;
8003 } 8238 }
8004 8239
8240
8005 private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack) 8241 private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack)
8006 { 8242 {
8007 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; 8243 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
@@ -11732,8 +11968,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11732 } 11968 }
11733 11969
11734 /// <summary> 11970 /// <summary>
11735 /// Send a response back to a client when it asks the asset server (via the region server) if it has
11736 /// its appearance texture cached.
11737 /// </summary> 11971 /// </summary>
11738 /// <remarks> 11972 /// <remarks>
11739 /// At the moment, we always reply that there is no cached texture. 11973 /// At the moment, we always reply that there is no cached texture.
@@ -11741,6 +11975,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11741 /// <param name="simclient"></param> 11975 /// <param name="simclient"></param>
11742 /// <param name="packet"></param> 11976 /// <param name="packet"></param>
11743 /// <returns></returns> 11977 /// <returns></returns>
11978 // TODO: Convert old handler to use new method
11979 /*protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11980 {
11981 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
11982
11983 if (cachedtex.AgentData.SessionID != SessionId)
11984 return false;
11985
11986
11987 List<CachedTextureRequestArg> requestArgs = new List<CachedTextureRequestArg>();
11988
11989 for (int i = 0; i < cachedtex.WearableData.Length; i++)
11990 {
11991 CachedTextureRequestArg arg = new CachedTextureRequestArg();
11992 arg.BakedTextureIndex = cachedtex.WearableData[i].TextureIndex;
11993 arg.WearableHashID = cachedtex.WearableData[i].ID;
11994
11995 requestArgs.Add(arg);
11996 }
11997
11998 CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest;
11999 if (handlerCachedTextureRequest != null)
12000 {
12001 handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs);
12002 }
12003
12004 return true;
12005 }*/
12006
11744 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) 12007 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11745 { 12008 {
11746 //m_log.Debug("texture cached: " + packet.ToString()); 12009 //m_log.Debug("texture cached: " + packet.ToString());
@@ -11899,6 +12162,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11899 return true; 12162 return true;
11900 } 12163 }
11901 12164
12165 /// <summary>
12166 /// Send a response back to a client when it asks the asset server (via the region server) if it has
12167 /// its appearance texture cached.
12168 /// </summary>
12169 /// <param name="avatar"></param>
12170 /// <param name="serial"></param>
12171 /// <param name="cachedTextures"></param>
12172 /// <returns></returns>
12173 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
12174 {
12175 ScenePresence presence = avatar as ScenePresence;
12176 if (presence == null)
12177 return;
12178
12179 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
12180
12181 // TODO: don't create new blocks if recycling an old packet
12182 cachedresp.AgentData.AgentID = m_agentId;
12183 cachedresp.AgentData.SessionID = m_sessionId;
12184 cachedresp.AgentData.SerialNum = serial;
12185 cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cachedTextures.Count];
12186
12187 for (int i = 0; i < cachedTextures.Count; i++)
12188 {
12189 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
12190 cachedresp.WearableData[i].TextureIndex = (byte)cachedTextures[i].BakedTextureIndex;
12191 cachedresp.WearableData[i].TextureID = cachedTextures[i].BakedTextureID;
12192 cachedresp.WearableData[i].HostName = new byte[0];
12193 }
12194
12195 cachedresp.Header.Zerocoded = true;
12196 OutPacket(cachedresp, ThrottleOutPacketType.Task);
12197 }
12198
11902 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet) 12199 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet)
11903 { 12200 {
11904 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; 12201 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
@@ -11924,8 +12221,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11924 if (part == null) 12221 if (part == null)
11925 { 12222 {
11926 // It's a ghost! tell the client to delete it from view. 12223 // It's a ghost! tell the client to delete it from view.
11927 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 12224 simClient.SendKillObject(new List<uint> { localId });
11928 new List<uint> { localId });
11929 } 12225 }
11930 else 12226 else
11931 { 12227 {
@@ -12299,6 +12595,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12299 12595
12300 shape.PCode = addPacket.ObjectData.PCode; 12596 shape.PCode = addPacket.ObjectData.PCode;
12301 shape.State = addPacket.ObjectData.State; 12597 shape.State = addPacket.ObjectData.State;
12598 shape.LastAttachPoint = addPacket.ObjectData.State;
12302 shape.PathBegin = addPacket.ObjectData.PathBegin; 12599 shape.PathBegin = addPacket.ObjectData.PathBegin;
12303 shape.PathEnd = addPacket.ObjectData.PathEnd; 12600 shape.PathEnd = addPacket.ObjectData.PathEnd;
12304 shape.PathScaleX = addPacket.ObjectData.PathScaleX; 12601 shape.PathScaleX = addPacket.ObjectData.PathScaleX;
@@ -12329,7 +12626,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12329 ClientInfo info = m_udpClient.GetClientInfo(); 12626 ClientInfo info = m_udpClient.GetClientInfo();
12330 12627
12331 info.proxyEP = null; 12628 info.proxyEP = null;
12332 info.agentcircuit = RequestClientInfo(); 12629 if (info.agentcircuit == null)
12630 info.agentcircuit = RequestClientInfo();
12333 12631
12334 return info; 12632 return info;
12335 } 12633 }
@@ -12712,11 +13010,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12712 OutPacket(dialog, ThrottleOutPacketType.Task); 13010 OutPacket(dialog, ThrottleOutPacketType.Task);
12713 } 13011 }
12714 13012
12715 public void StopFlying(ISceneEntity p) 13013 public void SendAgentTerseUpdate(ISceneEntity p)
12716 { 13014 {
12717 if (p is ScenePresence) 13015 if (p is ScenePresence)
12718 { 13016 {
12719 ScenePresence presence = p as ScenePresence; 13017// m_log.DebugFormat(
13018// "[LLCLIENTVIEW]: Immediately sending terse agent update for {0} to {1} in {2}",
13019// p.Name, Name, Scene.Name);
13020
12720 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities 13021 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities
12721 // There's no explicit message to send the client to tell it to stop flying.. it relies on the 13022 // There's no explicit message to send the client to tell it to stop flying.. it relies on the
12722 // velocity, collision plane and avatar height 13023 // velocity, collision plane and avatar height
@@ -12724,34 +13025,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12724 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air 13025 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air
12725 // when the avatar stands up 13026 // when the avatar stands up
12726 13027
12727 Vector3 pos = presence.AbsolutePosition;
12728
12729 if (presence.Appearance.AvatarHeight != 127.0f)
12730 pos += new Vector3(0f, 0f, (presence.Appearance.AvatarHeight/6f));
12731 else
12732 pos += new Vector3(0f, 0f, (1.56f/6f));
12733
12734 presence.AbsolutePosition = pos;
12735
12736 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
12737 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
12738 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
12739 // certain amount.. because the LLClient wouldn't land in that situation anyway.
12740
12741 // why are we still testing for this really old height value default???
12742 if (presence.Appearance.AvatarHeight != 127.0f)
12743 presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - presence.Appearance.AvatarHeight/6f);
12744 else
12745 presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f/6f));
12746
12747
12748 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = 13028 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block =
12749 CreateImprovedTerseBlock(p, false); 13029 CreateImprovedTerseBlock(p, false);
12750 13030
12751 const float TIME_DILATION = 1.0f; 13031 const float TIME_DILATION = 1.0f;
12752 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 13032 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12753 13033
12754
12755 ImprovedTerseObjectUpdatePacket packet 13034 ImprovedTerseObjectUpdatePacket packet
12756 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( 13035 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12757 PacketType.ImprovedTerseObjectUpdate); 13036 PacketType.ImprovedTerseObjectUpdate);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs
index 073c357..41dd4d1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs
@@ -206,6 +206,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
206 } 206 }
207 } 207 }
208 208
209 public bool HasUpdates()
210 {
211 J2KImage image = GetHighestPriorityImage();
212
213 return image != null && image.IsDecoded;
214 }
215
209 public bool ProcessImageQueue(int packetsToSend) 216 public bool ProcessImageQueue(int packetsToSend)
210 { 217 {
211 int packetsSent = 0; 218 int packetsSent = 0;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index e52ac37..bd4e617 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -31,6 +31,7 @@ using System.Net;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
36 37
@@ -81,6 +82,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
81 /// hooked to put more data on the empty queue</summary> 82 /// hooked to put more data on the empty queue</summary>
82 public event QueueEmpty OnQueueEmpty; 83 public event QueueEmpty OnQueueEmpty;
83 84
85 public event Func<ThrottleOutPacketTypeFlags, bool> HasUpdates;
86
84 /// <summary>AgentID for this client</summary> 87 /// <summary>AgentID for this client</summary>
85 public readonly UUID AgentID; 88 public readonly UUID AgentID;
86 /// <summary>The remote address of the connected client</summary> 89 /// <summary>The remote address of the connected client</summary>
@@ -161,6 +164,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
161 public bool m_deliverPackets = true; 164 public bool m_deliverPackets = true;
162 165
163 /// <summary> 166 /// <summary>
167 /// This is the percentage of the udp texture queue to add to the task queue since
168 /// textures are now generally handled through http.
169 /// </summary>
170 private double m_cannibalrate = 0.0;
171
172 private ClientInfo m_info = new ClientInfo();
173
174 /// <summary>
164 /// Default constructor 175 /// Default constructor
165 /// </summary> 176 /// </summary>
166 /// <param name="server">Reference to the UDP server this client is connected to</param> 177 /// <param name="server">Reference to the UDP server this client is connected to</param>
@@ -197,6 +208,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
197 // Create an array of token buckets for this clients different throttle categories 208 // Create an array of token buckets for this clients different throttle categories
198 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 209 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
199 210
211 m_cannibalrate = rates.CannibalizeTextureRate;
212
200 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 213 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
201 { 214 {
202 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 215 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
@@ -241,20 +254,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
241 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists 254 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
242 // of pending and needed ACKs for every client every time some method wants information about 255 // of pending and needed ACKs for every client every time some method wants information about
243 // this connection is a recipe for poor performance 256 // this connection is a recipe for poor performance
244 ClientInfo info = new ClientInfo(); 257
245 info.pendingAcks = new Dictionary<uint, uint>(); 258 m_info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate;
246 info.needAck = new Dictionary<uint, byte[]>(); 259 m_info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
247 260 m_info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
248 info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; 261 m_info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
249 info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; 262 m_info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
250 info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; 263 m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
251 info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; 264 m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
252 info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; 265 m_info.totalThrottle = (int)m_throttleCategory.DripRate;
253 info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 266
254 info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 267 return m_info;
255 info.totalThrottle = (int)m_throttleCategory.DripRate;
256
257 return info;
258 } 268 }
259 269
260 /// <summary> 270 /// <summary>
@@ -348,6 +358,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
348 texture = Math.Max(texture, LLUDPServer.MTU); 358 texture = Math.Max(texture, LLUDPServer.MTU);
349 asset = Math.Max(asset, LLUDPServer.MTU); 359 asset = Math.Max(asset, LLUDPServer.MTU);
350 360
361 // Since most textures are now delivered through http, make it possible
362 // to cannibalize some of the bw from the texture throttle to use for
363 // the task queue (e.g. object updates)
364 task = task + (int)(m_cannibalrate * texture);
365 texture = (int)((1 - m_cannibalrate) * texture);
366
351 //int total = resend + land + wind + cloud + task + texture + asset; 367 //int total = resend + land + wind + cloud + task + texture + asset;
352 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", 368 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
353 // AgentID, resend, land, wind, cloud, task, texture, asset, total); 369 // AgentID, resend, land, wind, cloud, task, texture, asset, total);
@@ -646,15 +662,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
646 /// <param name="categories">Throttle categories to fire the callback for</param> 662 /// <param name="categories">Throttle categories to fire the callback for</param>
647 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) 663 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
648 { 664 {
649 if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) 665// if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
666 if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
650 { 667 {
668 m_isQueueEmptyRunning = true;
669
670 int start = Environment.TickCount & Int32.MaxValue;
671 const int MIN_CALLBACK_MS = 30;
672
673 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
674 if (m_nextOnQueueEmpty == 0)
675 m_nextOnQueueEmpty = 1;
676
651 // Use a value of 0 to signal that FireQueueEmpty is running 677 // Use a value of 0 to signal that FireQueueEmpty is running
652 m_nextOnQueueEmpty = 0; 678// m_nextOnQueueEmpty = 0;
653 // Asynchronously run the callback 679
654 Util.FireAndForget(FireQueueEmpty, categories); 680 m_categories = categories;
681
682 if (HasUpdates(m_categories))
683 {
684 // Asynchronously run the callback
685 Util.FireAndForget(FireQueueEmpty, categories);
686 }
687 else
688 {
689 m_isQueueEmptyRunning = false;
690 }
655 } 691 }
656 } 692 }
657 693
694 private bool m_isQueueEmptyRunning;
695 private ThrottleOutPacketTypeFlags m_categories = 0;
696
658 /// <summary> 697 /// <summary>
659 /// Fires the OnQueueEmpty callback and sets the minimum time that it 698 /// Fires the OnQueueEmpty callback and sets the minimum time that it
660 /// can be called again 699 /// can be called again
@@ -664,22 +703,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
664 /// signature</param> 703 /// signature</param>
665 private void FireQueueEmpty(object o) 704 private void FireQueueEmpty(object o)
666 { 705 {
667 const int MIN_CALLBACK_MS = 30; 706// int start = Environment.TickCount & Int32.MaxValue;
707// const int MIN_CALLBACK_MS = 30;
668 708
669 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; 709// if (m_udpServer.IsRunningOutbound)
670 QueueEmpty callback = OnQueueEmpty; 710// {
671 711 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
672 int start = Environment.TickCount & Int32.MaxValue; 712 QueueEmpty callback = OnQueueEmpty;
673 713
674 if (callback != null) 714 if (callback != null)
675 { 715 {
676 try { callback(categories); } 716// if (m_udpServer.IsRunningOutbound)
677 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); } 717// {
678 } 718 try { callback(categories); }
719 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
720// }
721 }
722// }
723
724// m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
725// if (m_nextOnQueueEmpty == 0)
726// m_nextOnQueueEmpty = 1;
727
728// }
679 729
680 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; 730 m_isQueueEmptyRunning = false;
681 if (m_nextOnQueueEmpty == 0)
682 m_nextOnQueueEmpty = 1;
683 } 731 }
684 internal void ForceThrottleSetting(int throttle, int setting) 732 internal void ForceThrottleSetting(int throttle, int setting)
685 { 733 {
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 4154ef2..50dae2a 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -34,6 +34,7 @@ using System.Net.Sockets;
34using System.Reflection; 34using System.Reflection;
35using System.Threading; 35using System.Threading;
36using log4net; 36using log4net;
37using NDesk.Options;
37using Nini.Config; 38using Nini.Config;
38using OpenMetaverse.Packets; 39using OpenMetaverse.Packets;
39using OpenSim.Framework; 40using OpenSim.Framework;
@@ -62,20 +63,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP
62 m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager); 63 m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager);
63 } 64 }
64 65
65 public void NetworkStop()
66 {
67 m_udpServer.Stop();
68 }
69
70 public void AddScene(IScene scene) 66 public void AddScene(IScene scene)
71 { 67 {
72 m_udpServer.AddScene(scene); 68 m_udpServer.AddScene(scene);
73 69
74 StatsManager.RegisterStat( 70 StatsManager.RegisterStat(
75 new Stat( 71 new Stat(
72 "ClientLogoutsDueToNoReceives",
73 "Number of times a client has been logged out because no packets were received before the timeout.",
74 "",
75 "",
76 "clientstack",
77 scene.Name,
78 StatType.Pull,
79 MeasuresOfInterest.None,
80 stat => stat.Value = m_udpServer.ClientLogoutsDueToNoReceives,
81 StatVerbosity.Debug));
82
83 StatsManager.RegisterStat(
84 new Stat(
85 "IncomingUDPReceivesCount",
86 "Number of UDP receives performed",
87 "",
88 "",
89 "clientstack",
90 scene.Name,
91 StatType.Pull,
92 MeasuresOfInterest.AverageChangeOverTime,
93 stat => stat.Value = m_udpServer.UdpReceives,
94 StatVerbosity.Debug));
95
96 StatsManager.RegisterStat(
97 new Stat(
76 "IncomingPacketsProcessedCount", 98 "IncomingPacketsProcessedCount",
77 "Number of inbound UDP packets processed", 99 "Number of inbound LL protocol packets processed",
78 "Number of inbound UDP packets processed", 100 "",
79 "", 101 "",
80 "clientstack", 102 "clientstack",
81 scene.Name, 103 scene.Name,
@@ -83,6 +105,86 @@ namespace OpenSim.Region.ClientStack.LindenUDP
83 MeasuresOfInterest.AverageChangeOverTime, 105 MeasuresOfInterest.AverageChangeOverTime,
84 stat => stat.Value = m_udpServer.IncomingPacketsProcessed, 106 stat => stat.Value = m_udpServer.IncomingPacketsProcessed,
85 StatVerbosity.Debug)); 107 StatVerbosity.Debug));
108
109 StatsManager.RegisterStat(
110 new Stat(
111 "IncomingPacketsMalformedCount",
112 "Number of inbound UDP packets that could not be recognized as LL protocol packets.",
113 "",
114 "",
115 "clientstack",
116 scene.Name,
117 StatType.Pull,
118 MeasuresOfInterest.AverageChangeOverTime,
119 stat => stat.Value = m_udpServer.IncomingMalformedPacketCount,
120 StatVerbosity.Info));
121
122 StatsManager.RegisterStat(
123 new Stat(
124 "IncomingPacketsOrphanedCount",
125 "Number of inbound packets that were not initial connections packets and could not be associated with a viewer.",
126 "",
127 "",
128 "clientstack",
129 scene.Name,
130 StatType.Pull,
131 MeasuresOfInterest.AverageChangeOverTime,
132 stat => stat.Value = m_udpServer.IncomingOrphanedPacketCount,
133 StatVerbosity.Info));
134
135 StatsManager.RegisterStat(
136 new Stat(
137 "IncomingPacketsResentCount",
138 "Number of inbound packets that clients indicate are resends.",
139 "",
140 "",
141 "clientstack",
142 scene.Name,
143 StatType.Pull,
144 MeasuresOfInterest.AverageChangeOverTime,
145 stat => stat.Value = m_udpServer.IncomingPacketsResentCount,
146 StatVerbosity.Debug));
147
148 StatsManager.RegisterStat(
149 new Stat(
150 "OutgoingUDPSendsCount",
151 "Number of UDP sends performed",
152 "",
153 "",
154 "clientstack",
155 scene.Name,
156 StatType.Pull,
157 MeasuresOfInterest.AverageChangeOverTime,
158 stat => stat.Value = m_udpServer.UdpSends,
159 StatVerbosity.Debug));
160
161 StatsManager.RegisterStat(
162 new Stat(
163 "OutgoingPacketsResentCount",
164 "Number of packets resent because a client did not acknowledge receipt",
165 "",
166 "",
167 "clientstack",
168 scene.Name,
169 StatType.Pull,
170 MeasuresOfInterest.AverageChangeOverTime,
171 stat => stat.Value = m_udpServer.PacketsResentCount,
172 StatVerbosity.Debug));
173
174 StatsManager.RegisterStat(
175 new Stat(
176 "AverageUDPProcessTime",
177 "Average number of milliseconds taken to process each incoming UDP packet in a sample.",
178 "This is for initial receive processing which is separate from the later client LL packet processing stage.",
179 "ms",
180 "clientstack",
181 scene.Name,
182 StatType.Pull,
183 MeasuresOfInterest.None,
184 stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond,
185// stat =>
186// stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond, 7),
187 StatVerbosity.Debug));
86 } 188 }
87 189
88 public bool HandlesRegion(Location x) 190 public bool HandlesRegion(Location x)
@@ -107,10 +209,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
107 /// </summary> 209 /// </summary>
108 public class LLUDPServer : OpenSimUDPBase 210 public class LLUDPServer : OpenSimUDPBase
109 { 211 {
212 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
213
110 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> 214 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
111 public const int MTU = 1400; 215 public const int MTU = 1400;
112 216
113 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 217 /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary>
218 public int ClientLogoutsDueToNoReceives { get; private set; }
219
220 /// <summary>
221 /// Default packet debug level given to new clients
222 /// </summary>
223 public int DefaultClientPacketDebugLevel { get; set; }
114 224
115 /// <summary>The measured resolution of Environment.TickCount</summary> 225 /// <summary>The measured resolution of Environment.TickCount</summary>
116 public readonly float TickCountResolution; 226 public readonly float TickCountResolution;
@@ -184,6 +294,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
184 protected bool m_sendPing; 294 protected bool m_sendPing;
185 295
186 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 296 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
297
298 /// <summary>
299 /// Event used to signal when queued packets are available for sending.
300 /// </summary>
301 /// <remarks>
302 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling.
303 /// Some data is sent immediately and not queued. That data would not trigger this event.
304 /// </remarks>
305 private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
306
187 private Pool<IncomingPacket> m_incomingPacketPool; 307 private Pool<IncomingPacket> m_incomingPacketPool;
188 308
189 /// <summary> 309 /// <summary>
@@ -204,7 +324,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
204 324
205 public Socket Server { get { return null; } } 325 public Socket Server { get { return null; } }
206 326
207 private int m_malformedCount = 0; // Guard against a spamming attack 327 /// <summary>
328 /// Record how many packets have been resent
329 /// </summary>
330 internal int PacketsResentCount { get; set; }
331
332 /// <summary>
333 /// Record how many packets have been sent
334 /// </summary>
335 internal int PacketsSentCount { get; set; }
336
337 /// <summary>
338 /// Record how many incoming packets are indicated as resends by clients.
339 /// </summary>
340 internal int IncomingPacketsResentCount { get; set; }
341
342 /// <summary>
343 /// Record how many inbound packets could not be recognized as LLUDP packets.
344 /// </summary>
345 public int IncomingMalformedPacketCount { get; private set; }
346
347 /// <summary>
348 /// Record how many inbound packets could not be associated with a simulator circuit.
349 /// </summary>
350 public int IncomingOrphanedPacketCount { get; private set; }
208 351
209 /// <summary> 352 /// <summary>
210 /// Record current outgoing client for monitoring purposes. 353 /// Record current outgoing client for monitoring purposes.
@@ -461,6 +604,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
461 m_scene = (Scene)scene; 604 m_scene = (Scene)scene;
462 m_location = new Location(m_scene.RegionInfo.RegionHandle); 605 m_location = new Location(m_scene.RegionInfo.RegionHandle);
463 606
607 StatsManager.RegisterStat(
608 new Stat(
609 "InboxPacketsCount",
610 "Number of LL protocol packets waiting for the second stage of processing after initial receive.",
611 "Number of LL protocol packets waiting for the second stage of processing after initial receive.",
612 "",
613 "clientstack",
614 scene.Name,
615 StatType.Pull,
616 MeasuresOfInterest.AverageChangeOverTime,
617 stat => stat.Value = packetInbox.Count,
618 StatVerbosity.Debug));
619
464 // XXX: These stats are also pool stats but we register them separately since they are currently not 620 // XXX: These stats are also pool stats but we register them separately since they are currently not
465 // turned on and off by EnablePools()/DisablePools() 621 // turned on and off by EnablePools()/DisablePools()
466 StatsManager.RegisterStat( 622 StatsManager.RegisterStat(
@@ -521,6 +677,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
521 EnablePoolStats(); 677 EnablePoolStats();
522 678
523 MainConsole.Instance.Commands.AddCommand( 679 MainConsole.Instance.Commands.AddCommand(
680 "Debug", false, "debug lludp packet",
681 "debug lludp packet [--default] <level> [<avatar-first-name> <avatar-last-name>]",
682 "Turn on packet debugging",
683 "If level > 255 then all incoming and outgoing packets are logged.\n"
684 + "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n"
685 + "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n"
686 + "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n"
687 + "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n"
688 + "If level <= 0 then no packets are logged.\n"
689 + "If --default is specified then the level becomes the default logging level for all subsequent agents.\n"
690 + "In this case, you cannot also specify an avatar name.\n"
691 + "If an avatar name is given then only packets from that avatar are logged.",
692 HandlePacketCommand);
693
694 MainConsole.Instance.Commands.AddCommand(
524 "Debug", 695 "Debug",
525 false, 696 false,
526 "debug lludp start", 697 "debug lludp start",
@@ -559,10 +730,78 @@ namespace OpenSim.Region.ClientStack.LindenUDP
559 "debug lludp status", 730 "debug lludp status",
560 "Return status of LLUDP packet processing.", 731 "Return status of LLUDP packet processing.",
561 HandleStatusCommand); 732 HandleStatusCommand);
733
734 MainConsole.Instance.Commands.AddCommand(
735 "Debug",
736 false,
737 "debug lludp toggle agentupdate",
738 "debug lludp toggle agentupdate",
739 "Toggle whether agentupdate packets are processed or simply discarded.",
740 HandleAgentUpdateCommand);
741 }
742
743 private void HandlePacketCommand(string module, string[] args)
744 {
745 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
746 return;
747
748 bool setAsDefaultLevel = false;
749 OptionSet optionSet = new OptionSet().Add("default", o => setAsDefaultLevel = o != null);
750 List<string> filteredArgs = optionSet.Parse(args);
751
752 string name = null;
753
754 if (filteredArgs.Count == 6)
755 {
756 if (!setAsDefaultLevel)
757 {
758 name = string.Format("{0} {1}", filteredArgs[4], filteredArgs[5]);
759 }
760 else
761 {
762 MainConsole.Instance.OutputFormat("ERROR: Cannot specify a user name when setting default logging level");
763 return;
764 }
765 }
766
767 if (filteredArgs.Count > 3)
768 {
769 int newDebug;
770 if (int.TryParse(filteredArgs[3], out newDebug))
771 {
772 if (setAsDefaultLevel)
773 {
774 DefaultClientPacketDebugLevel = newDebug;
775 MainConsole.Instance.OutputFormat(
776 "Debug packet debug for new clients set to {0} in {1}", DefaultClientPacketDebugLevel, m_scene.Name);
777 }
778 else
779 {
780 m_scene.ForEachScenePresence(sp =>
781 {
782 if (name == null || sp.Name == name)
783 {
784 MainConsole.Instance.OutputFormat(
785 "Packet debug for {0} ({1}) set to {2} in {3}",
786 sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_scene.Name);
787
788 sp.ControllingClient.DebugPacketLevel = newDebug;
789 }
790 });
791 }
792 }
793 else
794 {
795 MainConsole.Instance.Output("Usage: debug lludp packet [--default] 0..255 [<first-name> <last-name>]");
796 }
797 }
562 } 798 }
563 799
564 private void HandleStartCommand(string module, string[] args) 800 private void HandleStartCommand(string module, string[] args)
565 { 801 {
802 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
803 return;
804
566 if (args.Length != 4) 805 if (args.Length != 4)
567 { 806 {
568 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>"); 807 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
@@ -580,6 +819,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
580 819
581 private void HandleStopCommand(string module, string[] args) 820 private void HandleStopCommand(string module, string[] args)
582 { 821 {
822 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
823 return;
824
583 if (args.Length != 4) 825 if (args.Length != 4)
584 { 826 {
585 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>"); 827 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
@@ -597,6 +839,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
597 839
598 private void HandlePoolCommand(string module, string[] args) 840 private void HandlePoolCommand(string module, string[] args)
599 { 841 {
842 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
843 return;
844
600 if (args.Length != 4) 845 if (args.Length != 4)
601 { 846 {
602 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); 847 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
@@ -627,8 +872,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
627 } 872 }
628 } 873 }
629 874
875 bool m_discardAgentUpdates;
876
877 private void HandleAgentUpdateCommand(string module, string[] args)
878 {
879 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
880 return;
881
882 m_discardAgentUpdates = !m_discardAgentUpdates;
883
884 MainConsole.Instance.OutputFormat(
885 "Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, m_scene.Name);
886 }
887
630 private void HandleStatusCommand(string module, string[] args) 888 private void HandleStatusCommand(string module, string[] args)
631 { 889 {
890 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
891 return;
892
632 MainConsole.Instance.OutputFormat( 893 MainConsole.Instance.OutputFormat(
633 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); 894 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
634 895
@@ -636,6 +897,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
636 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); 897 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
637 898
638 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); 899 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off");
900
901 MainConsole.Instance.OutputFormat(
902 "Packet debug level for new clients is {0}", DefaultClientPacketDebugLevel);
639 } 903 }
640 904
641 public bool HandlesRegion(Location x) 905 public bool HandlesRegion(Location x)
@@ -643,44 +907,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
643 return x == m_location; 907 return x == m_location;
644 } 908 }
645 909
646 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) 910// public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
647 { 911// {
648 // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way 912// // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
649 if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting) 913// if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
650 allowSplitting = false; 914// allowSplitting = false;
651 915//
652 if (allowSplitting && packet.HasVariableBlocks) 916// if (allowSplitting && packet.HasVariableBlocks)
653 { 917// {
654 byte[][] datas = packet.ToBytesMultiple(); 918// byte[][] datas = packet.ToBytesMultiple();
655 int packetCount = datas.Length; 919// int packetCount = datas.Length;
656 920//
657 if (packetCount < 1) 921// if (packetCount < 1)
658 m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length); 922// m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
659 923//
660 for (int i = 0; i < packetCount; i++) 924// for (int i = 0; i < packetCount; i++)
661 { 925// {
662 byte[] data = datas[i]; 926// byte[] data = datas[i];
663 m_scene.ForEachClient( 927// m_scene.ForEachClient(
664 delegate(IClientAPI client) 928// delegate(IClientAPI client)
665 { 929// {
666 if (client is LLClientView) 930// if (client is LLClientView)
667 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); 931// SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
668 } 932// }
669 ); 933// );
670 } 934// }
671 } 935// }
672 else 936// else
673 { 937// {
674 byte[] data = packet.ToBytes(); 938// byte[] data = packet.ToBytes();
675 m_scene.ForEachClient( 939// m_scene.ForEachClient(
676 delegate(IClientAPI client) 940// delegate(IClientAPI client)
677 { 941// {
678 if (client is LLClientView) 942// if (client is LLClientView)
679 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); 943// SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
680 } 944// }
681 ); 945// );
682 } 946// }
683 } 947// }
684 948
685 /// <summary> 949 /// <summary>
686 /// Start the process of sending a packet to the client. 950 /// Start the process of sending a packet to the client.
@@ -700,6 +964,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
700 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) 964 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
701 allowSplitting = false; 965 allowSplitting = false;
702 966
967 bool packetQueued = false;
968
703 if (allowSplitting && packet.HasVariableBlocks) 969 if (allowSplitting && packet.HasVariableBlocks)
704 { 970 {
705 byte[][] datas = packet.ToBytesMultiple(); 971 byte[][] datas = packet.ToBytesMultiple();
@@ -711,16 +977,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
711 for (int i = 0; i < packetCount; i++) 977 for (int i = 0; i < packetCount; i++)
712 { 978 {
713 byte[] data = datas[i]; 979 byte[] data = datas[i];
714 SendPacketData(udpClient, data, packet.Type, category, method); 980
981 if (!SendPacketData(udpClient, data, packet.Type, category, method))
982 packetQueued = true;
715 } 983 }
716 } 984 }
717 else 985 else
718 { 986 {
719 byte[] data = packet.ToBytes(); 987 byte[] data = packet.ToBytes();
720 SendPacketData(udpClient, data, packet.Type, category, method); 988 packetQueued = SendPacketData(udpClient, data, packet.Type, category, method);
721 } 989 }
722 990
723 PacketPool.Instance.ReturnPacket(packet); 991 PacketPool.Instance.ReturnPacket(packet);
992
993 if (packetQueued)
994 m_dataPresentEvent.Set();
724 } 995 }
725 996
726 /// <summary> 997 /// <summary>
@@ -734,7 +1005,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
734 /// The method to call if the packet is not acked by the client. If null, then a standard 1005 /// The method to call if the packet is not acked by the client. If null, then a standard
735 /// resend of the packet is done. 1006 /// resend of the packet is done.
736 /// </param> 1007 /// </param>
737 public void SendPacketData( 1008 /// <returns>true if the data was sent immediately, false if it was queued for sending</returns>
1009 public bool SendPacketData(
738 LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method) 1010 LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
739 { 1011 {
740 int dataLength = data.Length; 1012 int dataLength = data.Length;
@@ -807,7 +1079,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
807 // packet so that it isn't sent before a queued update packet. 1079 // packet so that it isn't sent before a queued update packet.
808 bool requestQueue = type == PacketType.KillObject; 1080 bool requestQueue = type == PacketType.KillObject;
809 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) 1081 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority))
1082 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue))
1083 {
810 SendPacketFinal(outgoingPacket); 1084 SendPacketFinal(outgoingPacket);
1085 return true;
1086 }
1087
1088 return false;
811 1089
812 #endregion Queue or Send 1090 #endregion Queue or Send
813 } 1091 }
@@ -883,7 +1161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
883 // Fire this out on a different thread so that we don't hold up outgoing packet processing for 1161 // Fire this out on a different thread so that we don't hold up outgoing packet processing for
884 // everybody else if this is being called due to an ack timeout. 1162 // everybody else if this is being called due to an ack timeout.
885 // This is the same as processing as the async process of a logout request. 1163 // This is the same as processing as the async process of a logout request.
886 Util.FireAndForget(o => DeactivateClientDueToTimeout(client)); 1164 Util.FireAndForget(o => DeactivateClientDueToTimeout(client, timeoutTicks));
887 1165
888 return; 1166 return;
889 } 1167 }
@@ -988,6 +1266,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
988 else 1266 else
989 { 1267 {
990 Interlocked.Increment(ref udpClient.PacketsResent); 1268 Interlocked.Increment(ref udpClient.PacketsResent);
1269
1270 // We're not going to worry about interlock yet since its not currently critical that this total count
1271 // is 100% correct
1272 PacketsResentCount++;
991 } 1273 }
992 1274
993 #endregion Sequence Number Assignment 1275 #endregion Sequence Number Assignment
@@ -995,6 +1277,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
995 // Stats tracking 1277 // Stats tracking
996 Interlocked.Increment(ref udpClient.PacketsSent); 1278 Interlocked.Increment(ref udpClient.PacketsSent);
997 1279
1280 // We're not going to worry about interlock yet since its not currently critical that this total count
1281 // is 100% correct
1282 PacketsSentCount++;
1283
998 // Put the UDP payload on the wire 1284 // Put the UDP payload on the wire
999 AsyncBeginSend(buffer); 1285 AsyncBeginSend(buffer);
1000 1286
@@ -1002,6 +1288,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1002 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 1288 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
1003 } 1289 }
1004 1290
1291 private void RecordMalformedInboundPacket(IPEndPoint endPoint)
1292 {
1293// if (m_malformedCount < 100)
1294// m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
1295
1296 IncomingMalformedPacketCount++;
1297
1298 if ((IncomingMalformedPacketCount % 10000) == 0)
1299 m_log.WarnFormat(
1300 "[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack. Last was from {1}",
1301 IncomingMalformedPacketCount, endPoint);
1302 }
1303
1005 public override void PacketReceived(UDPPacketBuffer buffer) 1304 public override void PacketReceived(UDPPacketBuffer buffer)
1006 { 1305 {
1007 // Debugging/Profiling 1306 // Debugging/Profiling
@@ -1023,6 +1322,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1023// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 1322// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
1024// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1323// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1025 1324
1325 RecordMalformedInboundPacket(endPoint);
1326
1026 return; // Drop undersized packet 1327 return; // Drop undersized packet
1027 } 1328 }
1028 1329
@@ -1041,6 +1342,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1041// "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}", 1342// "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}",
1042// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1343// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1043 1344
1345 RecordMalformedInboundPacket(endPoint);
1346
1044 return; // Malformed header 1347 return; // Malformed header
1045 } 1348 }
1046 1349
@@ -1056,34 +1359,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1056 // Only allocate a buffer for zerodecoding if the packet is zerocoded 1359 // Only allocate a buffer for zerodecoding if the packet is zerocoded
1057 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1360 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
1058 } 1361 }
1059 catch (MalformedDataException)
1060 {
1061 }
1062 catch (IndexOutOfRangeException)
1063 {
1064// m_log.WarnFormat(
1065// "[LLUDPSERVER]: Dropping short packet received from {0} in {1}",
1066// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1067
1068 return; // Drop short packet
1069 }
1070 catch (Exception e) 1362 catch (Exception e)
1071 { 1363 {
1072 if (m_malformedCount < 100) 1364 if (IncomingMalformedPacketCount < 100)
1073 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 1365 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
1074
1075 m_malformedCount++;
1076
1077 if ((m_malformedCount % 100000) == 0)
1078 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
1079 } 1366 }
1080 1367
1081 // Fail-safe check 1368 // Fail-safe check
1082 if (packet == null) 1369 if (packet == null)
1083 { 1370 {
1084 m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}:", 1371 if (IncomingMalformedPacketCount < 100)
1085 buffer.DataLength, buffer.RemoteEndPoint); 1372 {
1086 m_log.Error(Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); 1373 m_log.WarnFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}, data {2}:",
1374 buffer.DataLength, buffer.RemoteEndPoint, Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
1375 }
1376
1377 RecordMalformedInboundPacket(endPoint);
1378
1087 return; 1379 return;
1088 } 1380 }
1089 1381
@@ -1127,12 +1419,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1127 queue.Enqueue(buffer); 1419 queue.Enqueue(buffer);
1128 return; 1420 return;
1129 } 1421 }
1422 else if (packet.Type == PacketType.CompleteAgentMovement)
1423 {
1424 // Send ack straight away to let the viewer know that we got it.
1425 SendAckImmediate(endPoint, packet.Header.Sequence);
1426
1427 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1428 // buffer.
1429 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1430
1431 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1432
1433 return;
1434 }
1130 } 1435 }
1131 1436
1132 // Determine which agent this packet came from 1437 // Determine which agent this packet came from
1133 if (client == null || !(client is LLClientView)) 1438 if (client == null || !(client is LLClientView))
1134 { 1439 {
1135 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1440 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
1441
1442 IncomingOrphanedPacketCount++;
1443
1444 if ((IncomingOrphanedPacketCount % 10000) == 0)
1445 m_log.WarnFormat(
1446 "[LLUDPSERVER]: Received {0} orphaned packets so far. Last was from {1}",
1447 IncomingOrphanedPacketCount, endPoint);
1448
1136 return; 1449 return;
1137 } 1450 }
1138 1451
@@ -1211,6 +1524,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1211 1524
1212 #region Incoming Packet Accounting 1525 #region Incoming Packet Accounting
1213 1526
1527 // We're not going to worry about interlock yet since its not currently critical that this total count
1528 // is 100% correct
1529 if (packet.Header.Resent)
1530 IncomingPacketsResentCount++;
1531
1214 // Check the archive of received reliable packet IDs to see whether we already received this packet 1532 // Check the archive of received reliable packet IDs to see whether we already received this packet
1215 if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence)) 1533 if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence))
1216 { 1534 {
@@ -1233,6 +1551,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1233 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1551 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1234 #endregion BinaryStats 1552 #endregion BinaryStats
1235 1553
1554 if (packet.Type == PacketType.AgentUpdate)
1555 {
1556 if (m_discardAgentUpdates)
1557 return;
1558
1559 ((LLClientView)client).TotalAgentUpdates++;
1560
1561 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
1562
1563 LLClientView llClient = client as LLClientView;
1564 if (agentUpdate.AgentData.SessionID != client.SessionId
1565 || agentUpdate.AgentData.AgentID != client.AgentId
1566 || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) )
1567 {
1568 PacketPool.Instance.ReturnPacket(packet);
1569 return;
1570 }
1571 }
1572
1236 #region Ping Check Handling 1573 #region Ping Check Handling
1237 1574
1238 if (packet.Type == PacketType.StartPingCheck) 1575 if (packet.Type == PacketType.StartPingCheck)
@@ -1421,7 +1758,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1421 1758
1422 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1759 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1423 if (client != null) 1760 if (client != null)
1424 client.SceneAgent.SendInitialDataToMe(); 1761 {
1762 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1763 bool tp = (aCircuit.teleportFlags > 0);
1764 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
1765 if (!tp)
1766 client.SceneAgent.SendInitialDataToMe();
1767 }
1425 1768
1426 // Now we know we can handle more data 1769 // Now we know we can handle more data
1427 Thread.Sleep(200); 1770 Thread.Sleep(200);
@@ -1476,6 +1819,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1476 } 1819 }
1477 } 1820 }
1478 1821
1822 private void HandleCompleteMovementIntoRegion(object o)
1823 {
1824 IPEndPoint endPoint = null;
1825 IClientAPI client = null;
1826
1827 try
1828 {
1829 object[] array = (object[])o;
1830 endPoint = (IPEndPoint)array[0];
1831 CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1];
1832
1833 m_log.DebugFormat(
1834 "[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, m_scene.Name);
1835
1836 // Determine which agent this packet came from
1837 // We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination
1838 // simulator with no existing child presence, the viewer (at least LL 3.3.4) will send UseCircuitCode
1839 // and then CompleteAgentMovement immediately without waiting for an ack. As we are now handling these
1840 // packets asynchronously, we need to account for this thread proceeding more quickly than the
1841 // UseCircuitCode thread.
1842 int count = 40;
1843 while (count-- > 0)
1844 {
1845 if (m_scene.TryGetClient(endPoint, out client))
1846 {
1847 if (!client.IsActive)
1848 {
1849 // This check exists to catch a condition where the client has been closed by another thread
1850 // but has not yet been removed from the client manager (and possibly a new connection has
1851 // not yet been established).
1852 m_log.DebugFormat(
1853 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.",
1854 endPoint, client.Name, m_scene.Name);
1855 }
1856 else if (client.SceneAgent == null)
1857 {
1858 // This check exists to catch a condition where the new client has been added to the client
1859 // manager but the SceneAgent has not yet been set in Scene.AddNewAgent(). If we are too
1860 // eager, then the new ScenePresence may not have registered a listener for this messsage
1861 // before we try to process it.
1862 // XXX: A better long term fix may be to add the SceneAgent before the client is added to
1863 // the client manager
1864 m_log.DebugFormat(
1865 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.",
1866 endPoint, client.Name, m_scene.Name);
1867 }
1868 else
1869 {
1870 break;
1871 }
1872 }
1873 else
1874 {
1875 m_log.DebugFormat(
1876 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.",
1877 endPoint, m_scene.Name);
1878 }
1879
1880 Thread.Sleep(200);
1881 }
1882
1883 if (client == null)
1884 {
1885 m_log.DebugFormat(
1886 "[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.",
1887 endPoint, m_scene.Name);
1888
1889 return;
1890 }
1891 else if (!client.IsActive || client.SceneAgent == null)
1892 {
1893 // This check exists to catch a condition where the client has been closed by another thread
1894 // but has not yet been removed from the client manager.
1895 // The packet could be simply ignored but it is useful to know if this condition occurred for other debugging
1896 // purposes.
1897 m_log.DebugFormat(
1898 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.",
1899 endPoint, client.Name, m_scene.Name);
1900
1901 return;
1902 }
1903
1904 IncomingPacket incomingPacket1;
1905
1906 // Inbox insertion
1907 if (UsePools)
1908 {
1909 incomingPacket1 = m_incomingPacketPool.GetObject();
1910 incomingPacket1.Client = (LLClientView)client;
1911 incomingPacket1.Packet = packet;
1912 }
1913 else
1914 {
1915 incomingPacket1 = new IncomingPacket((LLClientView)client, packet);
1916 }
1917
1918 packetInbox.Enqueue(incomingPacket1);
1919 }
1920 catch (Exception e)
1921 {
1922 m_log.ErrorFormat(
1923 "[LLUDPSERVER]: CompleteAgentMovement handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1924 endPoint != null ? endPoint.ToString() : "n/a",
1925 client != null ? client.Name : "unknown",
1926 client != null ? client.AgentId.ToString() : "unknown",
1927 e.Message,
1928 e.StackTrace);
1929 }
1930 }
1931
1479 /// <summary> 1932 /// <summary>
1480 /// Send an ack immediately to the given endpoint. 1933 /// Send an ack immediately to the given endpoint.
1481 /// </summary> 1934 /// </summary>
@@ -1544,6 +1997,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1544 1997
1545 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1998 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1546 client.OnLogout += LogoutHandler; 1999 client.OnLogout += LogoutHandler;
2000 client.DebugPacketLevel = DefaultClientPacketDebugLevel;
1547 2001
1548 ((LLClientView)client).DisableFacelights = m_disableFacelights; 2002 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1549 2003
@@ -1562,21 +2016,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1562 /// regular client pings. 2016 /// regular client pings.
1563 /// </remarks> 2017 /// </remarks>
1564 /// <param name='client'></param> 2018 /// <param name='client'></param>
1565 private void DeactivateClientDueToTimeout(LLClientView client) 2019 /// <param name='timeoutTicks'></param>
2020 private void DeactivateClientDueToTimeout(LLClientView client, int timeoutTicks)
1566 { 2021 {
1567 lock (client.CloseSyncLock) 2022 lock (client.CloseSyncLock)
1568 { 2023 {
2024 ClientLogoutsDueToNoReceives++;
2025
1569 m_log.WarnFormat( 2026 m_log.WarnFormat(
1570 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", 2027 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
1571 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); 2028 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name);
1572
1573 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
1574 2029
1575 if (!client.SceneAgent.IsChildAgent) 2030 if (!client.SceneAgent.IsChildAgent)
1576 client.Kick("Simulator logged you out due to connection timeout"); 2031 client.Kick("Simulator logged you out due to connection timeout.");
1577
1578 client.CloseWithoutChecks(true);
1579 } 2032 }
2033
2034 m_scene.CloseAgent(client.AgentId, true);
1580 } 2035 }
1581 2036
1582 private void IncomingPacketHandler() 2037 private void IncomingPacketHandler()
@@ -1592,6 +2047,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1592 { 2047 {
1593 IncomingPacket incomingPacket = null; 2048 IncomingPacket incomingPacket = null;
1594 2049
2050 /*
1595 // HACK: This is a test to try and rate limit packet handling on Mono. 2051 // HACK: This is a test to try and rate limit packet handling on Mono.
1596 // If it works, a more elegant solution can be devised 2052 // If it works, a more elegant solution can be devised
1597 if (Util.FireAndForgetCount() < 2) 2053 if (Util.FireAndForgetCount() < 2)
@@ -1599,6 +2055,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1599 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping"); 2055 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping");
1600 Thread.Sleep(30); 2056 Thread.Sleep(30);
1601 } 2057 }
2058 */
1602 2059
1603 if (packetInbox.Dequeue(100, ref incomingPacket)) 2060 if (packetInbox.Dequeue(100, ref incomingPacket))
1604 { 2061 {
@@ -1694,8 +2151,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1694 2151
1695 // If nothing was sent, sleep for the minimum amount of time before a 2152 // If nothing was sent, sleep for the minimum amount of time before a
1696 // token bucket could get more tokens 2153 // token bucket could get more tokens
2154 //if (!m_packetSent)
2155 // Thread.Sleep((int)TickCountResolution);
2156 //
2157 // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with
2158 // modern mono it reduces CPU base load since there is no more continuous polling.
1697 if (!m_packetSent) 2159 if (!m_packetSent)
1698 Thread.Sleep((int)TickCountResolution); 2160 m_dataPresentEvent.WaitOne(100);
1699 2161
1700 Watchdog.UpdateThread(); 2162 Watchdog.UpdateThread();
1701 } 2163 }
@@ -1912,7 +2374,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1912 if (!client.IsLoggingOut) 2374 if (!client.IsLoggingOut)
1913 { 2375 {
1914 client.IsLoggingOut = true; 2376 client.IsLoggingOut = true;
1915 client.Close(false, false); 2377 m_scene.CloseAgent(client.AgentId, false);
1916 } 2378 }
1917 } 2379 }
1918 } 2380 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 7035e38..881e768 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -78,6 +78,36 @@ namespace OpenMetaverse
78 public bool IsRunningOutbound { get; private set; } 78 public bool IsRunningOutbound { get; private set; }
79 79
80 /// <summary> 80 /// <summary>
81 /// Number of UDP receives.
82 /// </summary>
83 public int UdpReceives { get; private set; }
84
85 /// <summary>
86 /// Number of UDP sends
87 /// </summary>
88 public int UdpSends { get; private set; }
89
90 /// <summary>
91 /// Number of receives over which to establish a receive time average.
92 /// </summary>
93 private readonly static int s_receiveTimeSamples = 500;
94
95 /// <summary>
96 /// Current number of samples taken to establish a receive time average.
97 /// </summary>
98 private int m_currentReceiveTimeSamples;
99
100 /// <summary>
101 /// Cumulative receive time for the sample so far.
102 /// </summary>
103 private int m_receiveTicksInCurrentSamplePeriod;
104
105 /// <summary>
106 /// The average time taken for each require receive in the last sample.
107 /// </summary>
108 public float AverageReceiveTicksForLastSamplePeriod { get; private set; }
109
110 /// <summary>
81 /// Default constructor 111 /// Default constructor
82 /// </summary> 112 /// </summary>
83 /// <param name="bindAddress">Local IP address to bind the server to</param> 113 /// <param name="bindAddress">Local IP address to bind the server to</param>
@@ -111,6 +141,8 @@ namespace OpenMetaverse
111 141
112 if (!IsRunningInbound) 142 if (!IsRunningInbound)
113 { 143 {
144 m_log.DebugFormat("[UDPBASE]: Starting inbound UDP loop");
145
114 const int SIO_UDP_CONNRESET = -1744830452; 146 const int SIO_UDP_CONNRESET = -1744830452;
115 147
116 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 148 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
@@ -151,6 +183,8 @@ namespace OpenMetaverse
151 /// </summary> 183 /// </summary>
152 public void StartOutbound() 184 public void StartOutbound()
153 { 185 {
186 m_log.DebugFormat("[UDPBASE]: Starting outbound UDP loop");
187
154 IsRunningOutbound = true; 188 IsRunningOutbound = true;
155 } 189 }
156 190
@@ -158,10 +192,8 @@ namespace OpenMetaverse
158 { 192 {
159 if (IsRunningInbound) 193 if (IsRunningInbound)
160 { 194 {
161 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 195 m_log.DebugFormat("[UDPBASE]: Stopping inbound UDP loop");
162 // will deny any more reader locks, in effect blocking all other send/receive 196
163 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other
164 // threads that the socket is closed.
165 IsRunningInbound = false; 197 IsRunningInbound = false;
166 m_udpSocket.Close(); 198 m_udpSocket.Close();
167 } 199 }
@@ -169,6 +201,8 @@ namespace OpenMetaverse
169 201
170 public void StopOutbound() 202 public void StopOutbound()
171 { 203 {
204 m_log.DebugFormat("[UDPBASE]: Stopping outbound UDP loop");
205
172 IsRunningOutbound = false; 206 IsRunningOutbound = false;
173 } 207 }
174 208
@@ -257,7 +291,16 @@ namespace OpenMetaverse
257 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); 291 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
258 } 292 }
259 } 293 }
260 catch (ObjectDisposedException) { } 294 catch (ObjectDisposedException e)
295 {
296 m_log.Error(
297 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
298 }
299 catch (Exception e)
300 {
301 m_log.Error(
302 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
303 }
261 } 304 }
262 } 305 }
263 306
@@ -267,17 +310,21 @@ namespace OpenMetaverse
267 // to AsyncBeginReceive 310 // to AsyncBeginReceive
268 if (IsRunningInbound) 311 if (IsRunningInbound)
269 { 312 {
313 UdpReceives++;
314
270 // Asynchronous mode will start another receive before the 315 // Asynchronous mode will start another receive before the
271 // callback for this packet is even fired. Very parallel :-) 316 // callback for this packet is even fired. Very parallel :-)
272 if (m_asyncPacketHandling) 317 if (m_asyncPacketHandling)
273 AsyncBeginReceive(); 318 AsyncBeginReceive();
274 319
275 // get the buffer that was created in AsyncBeginReceive
276 // this is the received data
277 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
278
279 try 320 try
280 { 321 {
322 // get the buffer that was created in AsyncBeginReceive
323 // this is the received data
324 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
325
326 int startTick = Util.EnvironmentTickCount();
327
281 // get the length of data actually read from the socket, store it with the 328 // get the length of data actually read from the socket, store it with the
282 // buffer 329 // buffer
283 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); 330 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
@@ -285,9 +332,42 @@ namespace OpenMetaverse
285 // call the abstract method PacketReceived(), passing the buffer that 332 // call the abstract method PacketReceived(), passing the buffer that
286 // has just been filled from the socket read. 333 // has just been filled from the socket read.
287 PacketReceived(buffer); 334 PacketReceived(buffer);
335
336 // If more than one thread can be calling AsyncEndReceive() at once (e.g. if m_asyncPacketHandler)
337 // then a particular stat may be inaccurate due to a race condition. We won't worry about this
338 // since this should be rare and won't cause a runtime problem.
339 if (m_currentReceiveTimeSamples >= s_receiveTimeSamples)
340 {
341 AverageReceiveTicksForLastSamplePeriod
342 = (float)m_receiveTicksInCurrentSamplePeriod / s_receiveTimeSamples;
343
344 m_receiveTicksInCurrentSamplePeriod = 0;
345 m_currentReceiveTimeSamples = 0;
346 }
347 else
348 {
349 m_receiveTicksInCurrentSamplePeriod += Util.EnvironmentTickCountSubtract(startTick);
350 m_currentReceiveTimeSamples++;
351 }
352 }
353 catch (SocketException se)
354 {
355 m_log.Error(
356 string.Format(
357 "[UDPBASE]: Error processing UDP end receive {0}, socket error code {1}. Exception ",
358 UdpReceives, se.ErrorCode),
359 se);
360 }
361 catch (ObjectDisposedException e)
362 {
363 m_log.Error(
364 string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
365 }
366 catch (Exception e)
367 {
368 m_log.Error(
369 string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
288 } 370 }
289 catch (SocketException) { }
290 catch (ObjectDisposedException) { }
291 finally 371 finally
292 { 372 {
293// if (UsePools) 373// if (UsePools)
@@ -298,14 +378,13 @@ namespace OpenMetaverse
298 if (!m_asyncPacketHandling) 378 if (!m_asyncPacketHandling)
299 AsyncBeginReceive(); 379 AsyncBeginReceive();
300 } 380 }
301
302 } 381 }
303 } 382 }
304 383
305 public void AsyncBeginSend(UDPPacketBuffer buf) 384 public void AsyncBeginSend(UDPPacketBuffer buf)
306 { 385 {
307 if (IsRunningOutbound) 386// if (IsRunningOutbound)
308 { 387// {
309 try 388 try
310 { 389 {
311 m_udpSocket.BeginSendTo( 390 m_udpSocket.BeginSendTo(
@@ -319,7 +398,7 @@ namespace OpenMetaverse
319 } 398 }
320 catch (SocketException) { } 399 catch (SocketException) { }
321 catch (ObjectDisposedException) { } 400 catch (ObjectDisposedException) { }
322 } 401// }
323 } 402 }
324 403
325 void AsyncEndSend(IAsyncResult result) 404 void AsyncEndSend(IAsyncResult result)
@@ -328,6 +407,8 @@ namespace OpenMetaverse
328 { 407 {
329// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; 408// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
330 m_udpSocket.EndSendTo(result); 409 m_udpSocket.EndSendTo(result);
410
411 UdpSends++;
331 } 412 }
332 catch (SocketException) { } 413 catch (SocketException) { }
333 catch (ObjectDisposedException) { } 414 catch (ObjectDisposedException) { }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
index 1fdc410..5a2bcee 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
@@ -145,39 +145,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
145 return packet; 145 return packet;
146 } 146 }
147 147
148 // private byte[] decoded_header = new byte[10];
149 private static PacketType GetType(byte[] bytes) 148 private static PacketType GetType(byte[] bytes)
150 { 149 {
151 byte[] decoded_header = new byte[10 + 8];
152 ushort id; 150 ushort id;
153 PacketFrequency freq; 151 PacketFrequency freq;
152 bool isZeroCoded = (bytes[0] & Helpers.MSG_ZEROCODED) != 0;
154 153
155 if ((bytes[0] & Helpers.MSG_ZEROCODED) != 0) 154 if (bytes[6] == 0xFF)
156 { 155 {
157 Helpers.ZeroDecode(bytes, 16, decoded_header); 156 if (bytes[7] == 0xFF)
158 }
159 else
160 {
161 Buffer.BlockCopy(bytes, 0, decoded_header, 0, 10);
162 }
163
164 if (decoded_header[6] == 0xFF)
165 {
166 if (decoded_header[7] == 0xFF)
167 { 157 {
168 id = (ushort) ((decoded_header[8] << 8) + decoded_header[9]);
169 freq = PacketFrequency.Low; 158 freq = PacketFrequency.Low;
159 if (isZeroCoded && bytes[8] == 0)
160 id = bytes[10];
161 else
162 id = (ushort)((bytes[8] << 8) + bytes[9]);
170 } 163 }
171 else 164 else
172 { 165 {
173 id = decoded_header[7];
174 freq = PacketFrequency.Medium; 166 freq = PacketFrequency.Medium;
167 id = bytes[7];
175 } 168 }
176 } 169 }
177 else 170 else
178 { 171 {
179 id = decoded_header[6];
180 freq = PacketFrequency.High; 172 freq = PacketFrequency.High;
173 id = bytes[6];
181 } 174 }
182 175
183 return Packet.GetType(id, freq); 176 return Packet.GetType(id, freq);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
index 98ef72f..f8d0c02 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index 556df30..9700224 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -33,6 +33,7 @@ using NUnit.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Packets; 34using OpenMetaverse.Packets;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Monitoring;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using OpenSim.Tests.Common; 38using OpenSim.Tests.Common;
38using OpenSim.Tests.Common.Mock; 39using OpenSim.Tests.Common.Mock;
@@ -69,6 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
69 { 70 {
70 base.SetUp(); 71 base.SetUp();
71 m_scene = new SceneHelpers().SetupScene(); 72 m_scene = new SceneHelpers().SetupScene();
73 StatsManager.SimExtraStats = new SimExtraStatsCollector();
72 } 74 }
73 75
74 /// <summary> 76 /// <summary>
@@ -198,7 +200,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
198 public void TestLogoutClientDueToAck() 200 public void TestLogoutClientDueToAck()
199 { 201 {
200 TestHelpers.InMethod(); 202 TestHelpers.InMethod();
201// TestHelpers.EnableLogging(); 203 TestHelpers.EnableLogging();
202 204
203 IniConfigSource ics = new IniConfigSource(); 205 IniConfigSource ics = new IniConfigSource();
204 IConfig config = ics.AddConfig("ClientStack.LindenUDP"); 206 IConfig config = ics.AddConfig("ClientStack.LindenUDP");
@@ -210,8 +212,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
210 212
211 ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); 213 ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
212 Assert.That(spAfterAckTimeout, Is.Null); 214 Assert.That(spAfterAckTimeout, Is.Null);
213
214// TestHelpers.DisableLogging();
215 } 215 }
216 216
217// /// <summary> 217// /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
index 7d9f581..575e54c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
@@ -29,6 +29,7 @@ using System;
29using System.IO; 29using System.IO;
30using System.Net; 30using System.Net;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using log4net.Config; 33using log4net.Config;
33using Nini.Config; 34using Nini.Config;
34using NUnit.Framework; 35using NUnit.Framework;
@@ -53,6 +54,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
53 [TestFixtureSetUp] 54 [TestFixtureSetUp]
54 public void FixtureInit() 55 public void FixtureInit()
55 { 56 {
57 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
58 Util.FireAndForgetMethod = FireAndForgetMethod.None;
59
56 using ( 60 using (
57 Stream resource 61 Stream resource
58 = GetType().Assembly.GetManifestResourceStream( 62 = GetType().Assembly.GetManifestResourceStream(
@@ -72,9 +76,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
72 } 76 }
73 } 77 }
74 78
79 [TestFixtureTearDown]
80 public void TearDown()
81 {
82 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
83 // threads. Possibly, later tests should be rewritten not to worry about such things.
84 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
85 }
86
75 [SetUp] 87 [SetUp]
76 public void SetUp() 88 public override void SetUp()
77 { 89 {
90 base.SetUp();
91
78 UUID userId = TestHelpers.ParseTail(0x3); 92 UUID userId = TestHelpers.ParseTail(0x3);
79 93
80 J2KDecoderModule j2kdm = new J2KDecoderModule(); 94 J2KDecoderModule j2kdm = new J2KDecoderModule();
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
index 119a677..e2178e5 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
@@ -52,17 +52,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
52 public override void Update(int frames) {} 52 public override void Update(int frames) {}
53 public override void LoadWorldMap() {} 53 public override void LoadWorldMap() {}
54 54
55 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 55 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
56 { 56 {
57 client.OnObjectName += RecordObjectNameCall; 57 client.OnObjectName += RecordObjectNameCall;
58 58
59 // FIXME 59 // FIXME
60 return null; 60 return null;
61 } 61 }
62 62
63 public override void RemoveClient(UUID agentID, bool someReason) {} 63 public override bool CloseAgent(UUID agentID, bool force) { return true; }
64// public override void CloseAllAgents(uint circuitcode) {} 64
65 public override bool CheckClient(UUID clientId, IPEndPoint endPoint) { return true; } 65 public override bool CheckClient(UUID clientId, IPEndPoint endPoint) { return true; }
66
66 public override void OtherRegionUp(GridRegion otherRegion) { } 67 public override void OtherRegionUp(GridRegion otherRegion) { }
67 68
68 public override bool TryGetScenePresence(UUID uuid, out ScenePresence sp) { sp = null; return false; } 69 public override bool TryGetScenePresence(UUID uuid, out ScenePresence sp) { sp = null; return false; }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
index c9aac0b..e5bae6e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
@@ -59,6 +59,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
59 /// <summary>Flag used to enable adaptive throttles</summary> 59 /// <summary>Flag used to enable adaptive throttles</summary>
60 public bool AdaptiveThrottlesEnabled; 60 public bool AdaptiveThrottlesEnabled;
61 61
62 /// <summary>Amount of the texture throttle to steal for the task throttle</summary>
63 public double CannibalizeTextureRate;
64
62 /// <summary> 65 /// <summary>
63 /// Default constructor 66 /// Default constructor
64 /// </summary> 67 /// </summary>
@@ -80,6 +83,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
80 Total = throttleConfig.GetInt("client_throttle_max_bps", 0); 83 Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
81 84
82 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); 85 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
86
87 CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f);
88 CannibalizeTextureRate = Util.Clamp<double>(CannibalizeTextureRate,0.0, 0.9);
83 } 89 }
84 catch (Exception) { } 90 catch (Exception) { }
85 } 91 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index da1ff2e..1e14f45 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -33,6 +33,7 @@ using OpenSim.Framework;
33 33
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces; 35using OpenSim.Services.Interfaces;
36using OpenSim.Region.Framework.Interfaces;
36 37
37namespace OpenSim.Region.CoreModules.Agent.AssetTransaction 38namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
38{ 39{
@@ -119,6 +120,14 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
119 } 120 }
120 else 121 else
121 { 122 {
123 // Check if the xfer is a terrain xfer
124 IEstateModule estateModule = m_Scene.RequestModuleInterface<IEstateModule>();
125 if (estateModule != null)
126 {
127 if (estateModule.IsTerrainXfer(xferID))
128 return;
129 }
130
122 m_log.ErrorFormat( 131 m_log.ErrorFormat(
123 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}", 132 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}",
124 xferID, packetID, data.Length); 133 xferID, packetID, data.Length);
diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
index 3764685..d9b0eff 100644
--- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
166 166
167 // Do Decode! 167 // Do Decode!
168 if (decode) 168 if (decode)
169 Decode(assetID, j2kData); 169 Util.FireAndForget(delegate { Decode(assetID, j2kData); });
170 } 170 }
171 } 171 }
172 172
diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
index f43305f..9b0e1f4 100644
--- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
@@ -194,10 +194,12 @@ namespace OpenSim.Region.CoreModules.Asset
194 194
195 #region IImprovedAssetCache Members 195 #region IImprovedAssetCache Members
196 196
197
198 public bool Check(string id) 197 public bool Check(string id)
199 { 198 {
200 return false; 199 AssetBase asset;
200
201 // XXX:This is probably not an efficient implementation.
202 return m_cache.TryGetValue(id, out asset);
201 } 203 }
202 204
203 /// <summary> 205 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
index 58ce61a..f720748 100644
--- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
@@ -114,7 +114,8 @@ namespace OpenSim.Region.CoreModules.Asset
114 // 114 //
115 public bool Check(string id) 115 public bool Check(string id)
116 { 116 {
117 return false; 117 // XXX This is probably not an efficient implementation.
118 return Get(id) != null;
118 } 119 }
119 120
120 public void Cache(AssetBase asset) 121 public void Cache(AssetBase asset)
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index d510d82..b270de9 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -31,17 +31,16 @@
31using System; 31using System;
32using System.IO; 32using System.IO;
33using System.Collections.Generic; 33using System.Collections.Generic;
34using System.Linq;
34using System.Reflection; 35using System.Reflection;
35using System.Runtime.Serialization; 36using System.Runtime.Serialization;
36using System.Runtime.Serialization.Formatters.Binary; 37using System.Runtime.Serialization.Formatters.Binary;
37using System.Threading; 38using System.Threading;
38using System.Timers; 39using System.Timers;
39
40using log4net; 40using log4net;
41using Nini.Config; 41using Nini.Config;
42using Mono.Addins; 42using Mono.Addins;
43using OpenMetaverse; 43using OpenMetaverse;
44
45using OpenSim.Framework; 44using OpenSim.Framework;
46using OpenSim.Framework.Console; 45using OpenSim.Framework.Console;
47using OpenSim.Region.Framework.Interfaces; 46using OpenSim.Region.Framework.Interfaces;
@@ -76,8 +75,6 @@ namespace OpenSim.Region.CoreModules.Asset
76 private static ulong m_RequestsForInprogress; 75 private static ulong m_RequestsForInprogress;
77 private static ulong m_DiskHits; 76 private static ulong m_DiskHits;
78 private static ulong m_MemoryHits; 77 private static ulong m_MemoryHits;
79 private static double m_HitRateMemory;
80 private static double m_HitRateFile;
81 78
82#if WAIT_ON_INPROGRESS_REQUESTS 79#if WAIT_ON_INPROGRESS_REQUESTS
83 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>(); 80 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>();
@@ -251,71 +248,68 @@ namespace OpenSim.Region.CoreModules.Asset
251 248
252 private void UpdateFileCache(string key, AssetBase asset) 249 private void UpdateFileCache(string key, AssetBase asset)
253 { 250 {
254 // TODO: Spawn this off to some seperate thread to do the actual writing 251 string filename = GetFileName(key);
255 if (asset != null)
256 {
257 string filename = GetFileName(key);
258 252
259 try 253 try
254 {
255 // If the file is already cached, don't cache it, just touch it so access time is updated
256 if (File.Exists(filename))
260 { 257 {
261 // If the file is already cached, don't cache it, just touch it so access time is updated 258 // We don't really want to know about sharing
262 if (File.Exists(filename)) 259 // violations here. If the file is locked, then
260 // the other thread has updated the time for us.
261 try
263 { 262 {
264 // We don't really want to know about sharing 263 lock (m_CurrentlyWriting)
265 // violations here. If the file is locked, then
266 // the other thread has updated the time for us.
267 try
268 { 264 {
269 lock (m_CurrentlyWriting) 265 if (!m_CurrentlyWriting.Contains(filename))
270 { 266 File.SetLastAccessTime(filename, DateTime.Now);
271 if (!m_CurrentlyWriting.Contains(filename))
272 File.SetLastAccessTime(filename, DateTime.Now);
273 }
274 } 267 }
275 catch 268 }
269 catch
270 {
271 }
272 }
273 else
274 {
275 // Once we start writing, make sure we flag that we're writing
276 // that object to the cache so that we don't try to write the
277 // same file multiple times.
278 lock (m_CurrentlyWriting)
279 {
280#if WAIT_ON_INPROGRESS_REQUESTS
281 if (m_CurrentlyWriting.ContainsKey(filename))
276 { 282 {
283 return;
277 } 284 }
278 } else { 285 else
279
280 // Once we start writing, make sure we flag that we're writing
281 // that object to the cache so that we don't try to write the
282 // same file multiple times.
283 lock (m_CurrentlyWriting)
284 { 286 {
285#if WAIT_ON_INPROGRESS_REQUESTS 287 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
286 if (m_CurrentlyWriting.ContainsKey(filename)) 288 }
287 {
288 return;
289 }
290 else
291 {
292 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
293 }
294 289
295#else 290#else
296 if (m_CurrentlyWriting.Contains(filename)) 291 if (m_CurrentlyWriting.Contains(filename))
297 { 292 {
298 return; 293 return;
299 }
300 else
301 {
302 m_CurrentlyWriting.Add(filename);
303 }
304#endif
305
306 } 294 }
295 else
296 {
297 m_CurrentlyWriting.Add(filename);
298 }
299#endif
307 300
308 Util.FireAndForget(
309 delegate { WriteFileCache(filename, asset); });
310 } 301 }
311 } 302
312 catch (Exception e) 303 Util.FireAndForget(
313 { 304 delegate { WriteFileCache(filename, asset); });
314 m_log.ErrorFormat(
315 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
316 asset.ID, e.Message, e.StackTrace);
317 } 305 }
318 } 306 }
307 catch (Exception e)
308 {
309 m_log.ErrorFormat(
310 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
311 asset.ID, e.Message, e.StackTrace);
312 }
319 } 313 }
320 314
321 public void Cache(AssetBase asset) 315 public void Cache(AssetBase asset)
@@ -350,15 +344,9 @@ namespace OpenSim.Region.CoreModules.Asset
350 344
351 private bool CheckFromMemoryCache(string id) 345 private bool CheckFromMemoryCache(string id)
352 { 346 {
353 AssetBase asset = null; 347 return m_MemoryCache.Contains(id);
354
355 if (m_MemoryCache.TryGetValue(id, out asset))
356 return true;
357
358 return false;
359 } 348 }
360 349
361
362 /// <summary> 350 /// <summary>
363 /// Try to get an asset from the file cache. 351 /// Try to get an asset from the file cache.
364 /// </summary> 352 /// </summary>
@@ -396,15 +384,16 @@ namespace OpenSim.Region.CoreModules.Asset
396 384
397 if (File.Exists(filename)) 385 if (File.Exists(filename))
398 { 386 {
399 FileStream stream = null;
400 try 387 try
401 { 388 {
402 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 389 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
403 BinaryFormatter bformatter = new BinaryFormatter(); 390 {
391 BinaryFormatter bformatter = new BinaryFormatter();
404 392
405 asset = (AssetBase)bformatter.Deserialize(stream); 393 asset = (AssetBase)bformatter.Deserialize(stream);
406 394
407 m_DiskHits++; 395 m_DiskHits++;
396 }
408 } 397 }
409 catch (System.Runtime.Serialization.SerializationException e) 398 catch (System.Runtime.Serialization.SerializationException e)
410 { 399 {
@@ -423,12 +412,6 @@ namespace OpenSim.Region.CoreModules.Asset
423 m_log.WarnFormat( 412 m_log.WarnFormat(
424 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", 413 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
425 filename, id, e.Message, e.StackTrace); 414 filename, id, e.Message, e.StackTrace);
426
427 }
428 finally
429 {
430 if (stream != null)
431 stream.Close();
432 } 415 }
433 } 416 }
434 417
@@ -440,36 +423,19 @@ namespace OpenSim.Region.CoreModules.Asset
440 bool found = false; 423 bool found = false;
441 424
442 string filename = GetFileName(id); 425 string filename = GetFileName(id);
426
443 if (File.Exists(filename)) 427 if (File.Exists(filename))
444 { 428 {
445 // actually check if we can open it, and so update expire
446 FileStream stream = null;
447 try 429 try
448 { 430 {
449 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 431 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
450 if (stream != null)
451 { 432 {
452 found = true; 433 if (stream != null)
453 stream.Close(); 434 found = true;
454 } 435 }
455
456 }
457 catch (System.Runtime.Serialization.SerializationException e)
458 {
459 found = false;
460 m_log.ErrorFormat(
461 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
462 filename, id, e.Message, e.StackTrace);
463
464 // If there was a problem deserializing the asset, the asset may
465 // either be corrupted OR was serialized under an old format
466 // {different version of AssetBase} -- we should attempt to
467 // delete it and re-cache
468 File.Delete(filename);
469 } 436 }
470 catch (Exception e) 437 catch (Exception e)
471 { 438 {
472 found = false;
473 m_log.ErrorFormat( 439 m_log.ErrorFormat(
474 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", 440 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
475 filename, id, e.Message, e.StackTrace); 441 filename, id, e.Message, e.StackTrace);
@@ -498,18 +464,9 @@ namespace OpenSim.Region.CoreModules.Asset
498 464
499 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) 465 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
500 { 466 {
501 m_HitRateFile = (double)m_DiskHits / m_Requests * 100.0;
502
503 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit"); 467 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit");
504 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Hit Rate {0}% for {1} requests", m_HitRateFile.ToString("0.00"), m_Requests);
505 468
506 if (m_MemoryCacheEnabled) 469 GenerateCacheHitReport().ForEach(l => m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0}", l));
507 {
508 m_HitRateMemory = (double)m_MemoryHits / m_Requests * 100.0;
509 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Hit Rate {0}% for {1} requests", m_HitRateMemory.ToString("0.00"), m_Requests);
510 }
511
512 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} unnessesary requests due to requests for assets that are currently downloading.", m_RequestsForInprogress);
513 } 470 }
514 471
515 return asset; 472 return asset;
@@ -530,11 +487,6 @@ namespace OpenSim.Region.CoreModules.Asset
530 return Get(id); 487 return Get(id);
531 } 488 }
532 489
533 public AssetBase CheckCached(string id)
534 {
535 return Get(id);
536 }
537
538 public void Expire(string id) 490 public void Expire(string id)
539 { 491 {
540 if (m_LogLevel >= 2) 492 if (m_LogLevel >= 2)
@@ -819,7 +771,7 @@ namespace OpenSim.Region.CoreModules.Asset
819 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 771 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
820 772
821 HashSet<UUID> uniqueUuids = new HashSet<UUID>(); 773 HashSet<UUID> uniqueUuids = new HashSet<UUID>();
822 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); 774 Dictionary<UUID, sbyte> assets = new Dictionary<UUID, sbyte>();
823 775
824 foreach (Scene s in m_Scenes) 776 foreach (Scene s in m_Scenes)
825 { 777 {
@@ -842,7 +794,7 @@ namespace OpenSim.Region.CoreModules.Asset
842 else if (storeUncached) 794 else if (storeUncached)
843 { 795 {
844 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); 796 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
845 if (cachedAsset == null && assets[assetID] != AssetType.Unknown) 797 if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown)
846 m_log.DebugFormat( 798 m_log.DebugFormat(
847 "[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", 799 "[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",
848 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); 800 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
@@ -891,45 +843,77 @@ namespace OpenSim.Region.CoreModules.Asset
891 } 843 }
892 } 844 }
893 845
846 private List<string> GenerateCacheHitReport()
847 {
848 List<string> outputLines = new List<string>();
849
850 double fileHitRate = (double)m_DiskHits / m_Requests * 100.0;
851 outputLines.Add(
852 string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests));
853
854 if (m_MemoryCacheEnabled)
855 {
856 double memHitRate = (double)m_MemoryHits / m_Requests * 100.0;
857
858 outputLines.Add(
859 string.Format("Memory Hit Rate: {0}% for {1} requests", memHitRate.ToString("0.00"), m_Requests));
860 }
861
862 outputLines.Add(
863 string.Format(
864 "Unnecessary requests due to requests for assets that are currently downloading: {0}",
865 m_RequestsForInprogress));
866
867 return outputLines;
868 }
869
894 #region Console Commands 870 #region Console Commands
895 private void HandleConsoleCommand(string module, string[] cmdparams) 871 private void HandleConsoleCommand(string module, string[] cmdparams)
896 { 872 {
873 ICommandConsole con = MainConsole.Instance;
874
897 if (cmdparams.Length >= 2) 875 if (cmdparams.Length >= 2)
898 { 876 {
899 string cmd = cmdparams[1]; 877 string cmd = cmdparams[1];
878
900 switch (cmd) 879 switch (cmd)
901 { 880 {
902 case "status": 881 case "status":
903 if (m_MemoryCacheEnabled) 882 if (m_MemoryCacheEnabled)
904 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Cache : {0} assets", m_MemoryCache.Count); 883 con.OutputFormat("Memory Cache: {0} assets", m_MemoryCache.Count);
905 else 884 else
906 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory cache disabled"); 885 con.OutputFormat("Memory cache disabled");
907 886
908 if (m_FileCacheEnabled) 887 if (m_FileCacheEnabled)
909 { 888 {
910 int fileCount = GetFileCacheCount(m_CacheDirectory); 889 int fileCount = GetFileCacheCount(m_CacheDirectory);
911 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Cache : {0} assets", fileCount); 890 con.OutputFormat("File Cache: {0} assets", fileCount);
891 }
892 else
893 {
894 con.Output("File cache disabled");
895 }
896
897 GenerateCacheHitReport().ForEach(l => con.Output(l));
898
899 if (m_FileCacheEnabled)
900 {
901 con.Output("Deep scans have previously been performed on the following regions:");
912 902
913 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac")) 903 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
914 { 904 {
915 m_log.Info("[FLOTSAM ASSET CACHE]: Deep scans have previously been performed on the following regions:");
916
917 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac",""); 905 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
918 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s); 906 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
919 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss")); 907 con.OutputFormat("Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
920 } 908 }
921 } 909 }
922 else
923 {
924 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache disabled");
925 }
926 910
927 break; 911 break;
928 912
929 case "clear": 913 case "clear":
930 if (cmdparams.Length < 2) 914 if (cmdparams.Length < 2)
931 { 915 {
932 m_log.Warn("[FLOTSAM ASSET CACHE]: Usage is fcache clear [file] [memory]"); 916 con.Output("Usage is fcache clear [file] [memory]");
933 break; 917 break;
934 } 918 }
935 919
@@ -953,11 +937,11 @@ namespace OpenSim.Region.CoreModules.Asset
953 if (m_MemoryCacheEnabled) 937 if (m_MemoryCacheEnabled)
954 { 938 {
955 m_MemoryCache.Clear(); 939 m_MemoryCache.Clear();
956 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache cleared."); 940 con.Output("Memory cache cleared.");
957 } 941 }
958 else 942 else
959 { 943 {
960 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache not enabled."); 944 con.Output("Memory cache not enabled.");
961 } 945 }
962 } 946 }
963 947
@@ -966,24 +950,22 @@ namespace OpenSim.Region.CoreModules.Asset
966 if (m_FileCacheEnabled) 950 if (m_FileCacheEnabled)
967 { 951 {
968 ClearFileCache(); 952 ClearFileCache();
969 m_log.Info("[FLOTSAM ASSET CACHE]: File cache cleared."); 953 con.Output("File cache cleared.");
970 } 954 }
971 else 955 else
972 { 956 {
973 m_log.Info("[FLOTSAM ASSET CACHE]: File cache not enabled."); 957 con.Output("File cache not enabled.");
974 } 958 }
975 } 959 }
976 960
977 break; 961 break;
978 962
979 case "assets": 963 case "assets":
980 m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); 964 con.Output("Ensuring assets are cached for all scenes.");
981 965
982 Util.FireAndForget(delegate { 966 Util.FireAndForget(delegate {
983 int assetReferenceTotal = TouchAllSceneAssets(true); 967 int assetReferenceTotal = TouchAllSceneAssets(true);
984 m_log.InfoFormat( 968 con.OutputFormat("Completed check with {0} assets.", assetReferenceTotal);
985 "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
986 assetReferenceTotal);
987 }); 969 });
988 970
989 break; 971 break;
@@ -991,7 +973,7 @@ namespace OpenSim.Region.CoreModules.Asset
991 case "expire": 973 case "expire":
992 if (cmdparams.Length < 3) 974 if (cmdparams.Length < 3)
993 { 975 {
994 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Invalid parameters for Expire, please specify a valid date & time", cmd); 976 con.OutputFormat("Invalid parameters for Expire, please specify a valid date & time", cmd);
995 break; 977 break;
996 } 978 }
997 979
@@ -1009,28 +991,27 @@ namespace OpenSim.Region.CoreModules.Asset
1009 991
1010 if (!DateTime.TryParse(s_expirationDate, out expirationDate)) 992 if (!DateTime.TryParse(s_expirationDate, out expirationDate))
1011 { 993 {
1012 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} is not a valid date & time", cmd); 994 con.OutputFormat("{0} is not a valid date & time", cmd);
1013 break; 995 break;
1014 } 996 }
1015 997
1016 if (m_FileCacheEnabled) 998 if (m_FileCacheEnabled)
1017 CleanExpiredFiles(m_CacheDirectory, expirationDate); 999 CleanExpiredFiles(m_CacheDirectory, expirationDate);
1018 else 1000 else
1019 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache not active, not clearing."); 1001 con.OutputFormat("File cache not active, not clearing.");
1020 1002
1021 break; 1003 break;
1022 default: 1004 default:
1023 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Unknown command {0}", cmd); 1005 con.OutputFormat("Unknown command {0}", cmd);
1024 break; 1006 break;
1025 } 1007 }
1026 } 1008 }
1027 else if (cmdparams.Length == 1) 1009 else if (cmdparams.Length == 1)
1028 { 1010 {
1029 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache status - Display cache status"); 1011 con.Output("fcache assets - Attempt a deep cache of all assets in all scenes");
1030 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearmem - Remove all assets cached in memory"); 1012 con.Output("fcache expire <datetime> - Purge assets older then the specified date & time");
1031 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearfile - Remove all assets cached on disk"); 1013 con.Output("fcache clear [file] [memory] - Remove cached assets");
1032 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache cachescenes - Attempt a deep cache of all assets in all scenes"); 1014 con.Output("fcache status - Display cache status");
1033 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache <datetime> - Purge assets older then the specified date & time");
1034 } 1015 }
1035 } 1016 }
1036 1017
@@ -1050,11 +1031,6 @@ namespace OpenSim.Region.CoreModules.Asset
1050 return asset.Data; 1031 return asset.Data;
1051 } 1032 }
1052 1033
1053 public bool CheckData(string id)
1054 {
1055 return Check(id); ;
1056 }
1057
1058 public bool Get(string id, object sender, AssetRetrieved handler) 1034 public bool Get(string id, object sender, AssetRetrieved handler)
1059 { 1035 {
1060 AssetBase asset = Get(id); 1036 AssetBase asset = Get(id);
diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
index ce9b546..5f76ac2 100644
--- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
@@ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.Asset
117 117
118 public bool Check(string id) 118 public bool Check(string id)
119 { 119 {
120 return false; 120 return m_Cache.Contains(id);
121 } 121 }
122 122
123 public void Cache(AssetBase asset) 123 public void Cache(AssetBase asset)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 6495f3f..d47ca4b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.IO; 31using System.IO;
32using System.Threading;
32using System.Xml; 33using System.Xml;
33using log4net; 34using log4net;
34using Mono.Addins; 35using Mono.Addins;
@@ -51,6 +52,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 53
53 public int DebugLevel { get; set; } 54 public int DebugLevel { get; set; }
55
56 /// <summary>
57 /// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in/changes
58 /// outfit or many avatars with a medium levels of attachments login/change outfit simultaneously.
59 /// </summary>
60 /// <remarks>
61 /// A value of 0 will apply no pause. The pause is specified in milliseconds.
62 /// </remarks>
63 public int ThrottlePer100PrimsRezzed { get; set; }
54 64
55 private Scene m_scene; 65 private Scene m_scene;
56 private IInventoryAccessModule m_invAccessModule; 66 private IInventoryAccessModule m_invAccessModule;
@@ -67,18 +77,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
67 { 77 {
68 IConfig config = source.Configs["Attachments"]; 78 IConfig config = source.Configs["Attachments"];
69 if (config != null) 79 if (config != null)
80 {
70 Enabled = config.GetBoolean("Enabled", true); 81 Enabled = config.GetBoolean("Enabled", true);
82
83 ThrottlePer100PrimsRezzed = config.GetInt("ThrottlePer100PrimsRezzed", 0);
84 }
71 else 85 else
86 {
72 Enabled = true; 87 Enabled = true;
88 }
73 } 89 }
74 90
75 public void AddRegion(Scene scene) 91 public void AddRegion(Scene scene)
76 { 92 {
77 m_scene = scene; 93 m_scene = scene;
78 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
79
80 if (Enabled) 94 if (Enabled)
81 { 95 {
96 // Only register module with scene if it is enabled. All callers check for a null attachments module.
97 // Ideally, there should be a null attachments module for when this core attachments module has been
98 // disabled. Registering only when enabled allows for other attachments module implementations.
99 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
82 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 100 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
83 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true); 101 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
84 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false); 102 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);
@@ -86,24 +104,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
86 MainConsole.Instance.Commands.AddCommand( 104 MainConsole.Instance.Commands.AddCommand(
87 "Debug", 105 "Debug",
88 false, 106 false,
89 "debug attachments", 107 "debug attachments log",
90 "debug attachments [0|1]", 108 "debug attachments log [0|1]",
91 "Turn on attachments debugging\n" 109 "Turn on attachments debug logging",
92 + " <= 0 - turns off debugging\n" 110 " <= 0 - turns off debug logging\n"
93 + " >= 1 - turns on attachment message logging\n", 111 + " >= 1 - turns on attachment message debug logging",
94 HandleDebugAttachments); 112 HandleDebugAttachmentsLog);
113
114 MainConsole.Instance.Commands.AddCommand(
115 "Debug",
116 false,
117 "debug attachments throttle",
118 "debug attachments throttle <ms>",
119 "Turn on attachments throttling.",
120 "This requires a millisecond value. " +
121 " == 0 - disable throttling.\n"
122 + " > 0 - sleeps for this number of milliseconds per 100 prims rezzed.",
123 HandleDebugAttachmentsThrottle);
124
125 MainConsole.Instance.Commands.AddCommand(
126 "Debug",
127 false,
128 "debug attachments status",
129 "debug attachments status",
130 "Show current attachments debug status",
131 HandleDebugAttachmentsStatus);
95 } 132 }
96 133
97 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI 134 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
98 } 135 }
99 136
100 private void HandleDebugAttachments(string module, string[] args) 137 private void HandleDebugAttachmentsLog(string module, string[] args)
101 { 138 {
102 int debugLevel; 139 int debugLevel;
103 140
104 if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) 141 if (!(args.Length == 4 && int.TryParse(args[3], out debugLevel)))
105 { 142 {
106 MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]"); 143 MainConsole.Instance.OutputFormat("Usage: debug attachments log [0|1]");
107 } 144 }
108 else 145 else
109 { 146 {
@@ -113,6 +150,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
113 } 150 }
114 } 151 }
115 152
153 private void HandleDebugAttachmentsThrottle(string module, string[] args)
154 {
155 int ms;
156
157 if (args.Length == 4 && int.TryParse(args[3], out ms))
158 {
159 ThrottlePer100PrimsRezzed = ms;
160 MainConsole.Instance.OutputFormat(
161 "Attachments rez throttle per 100 prims is now {0} in {1}", ThrottlePer100PrimsRezzed, m_scene.Name);
162
163 return;
164 }
165
166 MainConsole.Instance.OutputFormat("Usage: debug attachments throttle <ms>");
167 }
168
169 private void HandleDebugAttachmentsStatus(string module, string[] args)
170 {
171 MainConsole.Instance.OutputFormat("Settings for {0}", m_scene.Name);
172 MainConsole.Instance.OutputFormat("Debug logging level: {0}", DebugLevel);
173 MainConsole.Instance.OutputFormat("Throttle per 100 prims: {0}ms", ThrottlePer100PrimsRezzed);
174 }
175
116 /// <summary> 176 /// <summary>
117 /// Listen for client triggered running state changes so that we can persist the script's object if necessary. 177 /// Listen for client triggered running state changes so that we can persist the script's object if necessary.
118 /// </summary> 178 /// </summary>
@@ -273,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
273 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 333 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
274 foreach (AvatarAttachment attach in attachments) 334 foreach (AvatarAttachment attach in attachments)
275 { 335 {
276 uint p = (uint)attach.AttachPoint; 336 uint attachmentPt = (uint)attach.AttachPoint;
277 337
278// m_log.DebugFormat( 338// m_log.DebugFormat(
279// "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", 339// "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}",
@@ -302,13 +362,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
302 // If we're an NPC then skip all the item checks and manipulations since we don't have an 362 // If we're an NPC then skip all the item checks and manipulations since we don't have an
303 // inventory right now. 363 // inventory right now.
304 RezSingleAttachmentFromInventoryInternal( 364 RezSingleAttachmentFromInventoryInternal(
305 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, d); 365 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d);
306 } 366 }
307 catch (Exception e) 367 catch (Exception e)
308 { 368 {
309 UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; 369 UUID agentId = (sp.ControllingClient == null) ? default(UUID) : sp.ControllingClient.AgentId;
310 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", 370 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}",
311 attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace); 371 attach.ItemID, attach.AssetID, attachmentPt, agentId, e.Message, e.StackTrace);
312 } 372 }
313 } 373 }
314 } 374 }
@@ -422,13 +482,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
422 attachPos = Vector3.Zero; 482 attachPos = Vector3.Zero;
423 } 483 }
424 484
425 // AttachmentPt 0 (default) means the client chose to 'wear' the attachment. 485 // if the attachment point is the same as previous, make sure we get the saved
486 // position info.
487 if (attachmentPt != 0 && attachmentPt == group.RootPart.Shape.LastAttachPoint)
488 {
489 attachPos = group.RootPart.AttachedPos;
490 }
491
492 // AttachmentPt 0 means the client chose to 'wear' the attachment.
426 if (attachmentPt == (uint)AttachmentPoint.Default) 493 if (attachmentPt == (uint)AttachmentPoint.Default)
427 { 494 {
428 // Check object for stored attachment point 495 // Check object for stored attachment point
429 attachmentPt = group.AttachmentPoint; 496 attachmentPt = group.AttachmentPoint;
430 } 497 }
431 498
499 // if we didn't find an attach point, look for where it was last attached
500 if (attachmentPt == 0)
501 {
502 attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint;
503 attachPos = group.RootPart.AttachedPos;
504 group.HasGroupChanged = true;
505 }
506
432 // if we still didn't find a suitable attachment point....... 507 // if we still didn't find a suitable attachment point.......
433 if (attachmentPt == 0) 508 if (attachmentPt == 0)
434 { 509 {
@@ -610,6 +685,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
610 if (changed && m_scene.AvatarFactory != null) 685 if (changed && m_scene.AvatarFactory != null)
611 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 686 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
612 687
688 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
689
613 sp.RemoveAttachment(so); 690 sp.RemoveAttachment(so);
614 so.FromItemID = UUID.Zero; 691 so.FromItemID = UUID.Zero;
615 692
@@ -841,7 +918,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
841 m_scene.ForEachClient( 918 m_scene.ForEachClient(
842 client => 919 client =>
843 { if (client.AgentId != so.AttachedAvatar) 920 { if (client.AgentId != so.AttachedAvatar)
844 client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId }); 921 client.SendKillObject(new List<uint>() { so.LocalId });
845 }); 922 });
846 } 923 }
847 924
@@ -982,8 +1059,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
982 1059
983 if (DebugLevel > 0) 1060 if (DebugLevel > 0)
984 m_log.DebugFormat( 1061 m_log.DebugFormat(
985 "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", 1062 "[ATTACHMENTS MODULE]: Rezzed single object {0} with {1} prims for attachment to {2} on point {3} in {4}",
986 objatt.Name, sp.Name, attachmentPt, m_scene.Name); 1063 objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
987 1064
988 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 1065 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
989 objatt.HasGroupChanged = false; 1066 objatt.HasGroupChanged = false;
@@ -1020,7 +1097,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1020 } 1097 }
1021 1098
1022 if (tainted) 1099 if (tainted)
1023 objatt.HasGroupChanged = true; 1100 objatt.HasGroupChanged = true;
1101
1102 if (ThrottlePer100PrimsRezzed > 0)
1103 {
1104 int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed);
1105
1106 if (DebugLevel > 0)
1107 m_log.DebugFormat(
1108 "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}",
1109 throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
1110
1111 Thread.Sleep(throttleMs);
1112 }
1024 1113
1025 return objatt; 1114 return objatt;
1026 } 1115 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 1a38619..f023e77 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -38,6 +38,8 @@ using NUnit.Framework;
38using OpenMetaverse; 38using OpenMetaverse;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Communications; 40using OpenSim.Framework.Communications;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Region.CoreModules.Avatar.Attachments; 43using OpenSim.Region.CoreModules.Avatar.Attachments;
42using OpenSim.Region.CoreModules.Framework; 44using OpenSim.Region.CoreModules.Framework;
43using OpenSim.Region.CoreModules.Framework.EntityTransfer; 45using OpenSim.Region.CoreModules.Framework.EntityTransfer;
@@ -717,7 +719,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
717 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 719 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
718 720
719 m_numberOfAttachEventsFired = 0; 721 m_numberOfAttachEventsFired = 0;
720 scene.IncomingCloseAgent(presence.UUID, false); 722 scene.CloseAgent(presence.UUID, false);
721 723
722 // Check that we can't retrieve this attachment from the scene. 724 // Check that we can't retrieve this attachment from the scene.
723 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 725 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
@@ -797,11 +799,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
797 } 799 }
798 800
799 [Test] 801 [Test]
800 public void TestSameSimulatorNeighbouringRegionsTeleport() 802 public void TestSameSimulatorNeighbouringRegionsTeleportV1()
801 { 803 {
802 TestHelpers.InMethod(); 804 TestHelpers.InMethod();
803// TestHelpers.EnableLogging(); 805// TestHelpers.EnableLogging();
804 806
807 BaseHttpServer httpServer = new BaseHttpServer(99999);
808 MainServer.AddHttpServer(httpServer);
809 MainServer.Instance = httpServer;
810
805 AttachmentsModule attModA = new AttachmentsModule(); 811 AttachmentsModule attModA = new AttachmentsModule();
806 AttachmentsModule attModB = new AttachmentsModule(); 812 AttachmentsModule attModB = new AttachmentsModule();
807 EntityTransferModule etmA = new EntityTransferModule(); 813 EntityTransferModule etmA = new EntityTransferModule();
@@ -830,14 +836,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
830 SceneHelpers.SetupSceneModules( 836 SceneHelpers.SetupSceneModules(
831 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); 837 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
832 838
839 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
840 lscm.ServiceVersion = "SIMULATION/0.1";
841
833 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); 842 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
834 843
835 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); 844 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
836 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 845 TestClient tc = new TestClient(acd, sceneA);
837 List<TestClient> destinationTestClients = new List<TestClient>(); 846 List<TestClient> destinationTestClients = new List<TestClient>();
838 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 847 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
839 848
840 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 849 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
841 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32); 850 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
842 851
843 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20); 852 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
@@ -895,5 +904,115 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
895 // Check events 904 // Check events
896 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 905 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
897 } 906 }
907
908 [Test]
909 public void TestSameSimulatorNeighbouringRegionsTeleportV2()
910 {
911 TestHelpers.InMethod();
912// TestHelpers.EnableLogging();
913
914 BaseHttpServer httpServer = new BaseHttpServer(99999);
915 MainServer.AddHttpServer(httpServer);
916 MainServer.Instance = httpServer;
917
918 AttachmentsModule attModA = new AttachmentsModule();
919 AttachmentsModule attModB = new AttachmentsModule();
920 EntityTransferModule etmA = new EntityTransferModule();
921 EntityTransferModule etmB = new EntityTransferModule();
922 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
923
924 IConfigSource config = new IniConfigSource();
925 IConfig modulesConfig = config.AddConfig("Modules");
926 modulesConfig.Set("EntityTransferModule", etmA.Name);
927 modulesConfig.Set("SimulationServices", lscm.Name);
928
929 modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule");
930
931 SceneHelpers sh = new SceneHelpers();
932 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
933 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
934
935 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
936 SceneHelpers.SetupSceneModules(
937 sceneA, config, new CapabilitiesModule(), etmA, attModA, new BasicInventoryAccessModule());
938 SceneHelpers.SetupSceneModules(
939 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
940
941 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
942
943 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
944 TestClient tc = new TestClient(acd, sceneA);
945 List<TestClient> destinationTestClients = new List<TestClient>();
946 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
947
948 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
949 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
950
951 Assert.That(destinationTestClients.Count, Is.EqualTo(1));
952 Assert.That(destinationTestClients[0], Is.Not.Null);
953
954 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
955
956 sceneA.AttachmentsModule.RezSingleAttachmentFromInventory(
957 beforeTeleportSp, attItem.ID, (uint)AttachmentPoint.Chest);
958
959 Vector3 teleportPosition = new Vector3(10, 11, 12);
960 Vector3 teleportLookAt = new Vector3(20, 21, 22);
961
962 // Here, we need to make clientA's receipt of SendRegionTeleport trigger clientB's CompleteMovement(). This
963 // is to operate the teleport V2 mechanism where the EntityTransferModule will first request the client to
964 // CompleteMovement to the region and then call UpdateAgent to the destination region to confirm the receipt
965 // Both these operations will occur on different threads and will wait for each other.
966 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1
967 // test protocol, where we are trying to avoid unpredictable async operations in regression tests.
968 tc.OnTestClientSendRegionTeleport
969 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL)
970 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null);
971
972 m_numberOfAttachEventsFired = 0;
973 sceneA.RequestTeleportLocation(
974 beforeTeleportSp.ControllingClient,
975 sceneB.RegionInfo.RegionHandle,
976 teleportPosition,
977 teleportLookAt,
978 (uint)TeleportFlags.ViaLocation);
979
980 // Check attachments have made it into sceneB
981 ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID);
982
983 // This is appearance data, as opposed to actually rezzed attachments
984 List<AvatarAttachment> sceneBAttachments = afterTeleportSceneBSp.Appearance.GetAttachments();
985 Assert.That(sceneBAttachments.Count, Is.EqualTo(1));
986 Assert.That(sceneBAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
987 Assert.That(sceneBAttachments[0].ItemID, Is.EqualTo(attItem.ID));
988 Assert.That(sceneBAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
989 Assert.That(afterTeleportSceneBSp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
990
991 // This is the actual attachment
992 List<SceneObjectGroup> actualSceneBAttachments = afterTeleportSceneBSp.GetAttachments();
993 Assert.That(actualSceneBAttachments.Count, Is.EqualTo(1));
994 SceneObjectGroup actualSceneBAtt = actualSceneBAttachments[0];
995 Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name));
996 Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest));
997
998 Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1));
999
1000 // Check attachments have been removed from sceneA
1001 ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID);
1002
1003 // Since this is appearance data, it is still present on the child avatar!
1004 List<AvatarAttachment> sceneAAttachments = afterTeleportSceneASp.Appearance.GetAttachments();
1005 Assert.That(sceneAAttachments.Count, Is.EqualTo(1));
1006 Assert.That(afterTeleportSceneASp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
1007
1008 // This is the actual attachment, which should no longer exist
1009 List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments();
1010 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
1011
1012 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
1013
1014 // Check events
1015 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
1016 }
898 } 1017 }
899} 1018}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index bc79944..09cc998 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -55,6 +55,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
55 55
56 private int m_savetime = 5; // seconds to wait before saving changed appearance 56 private int m_savetime = 5; // seconds to wait before saving changed appearance
57 private int m_sendtime = 2; // seconds to wait before sending changed appearance 57 private int m_sendtime = 2; // seconds to wait before sending changed appearance
58 private bool m_reusetextures = false;
58 59
59 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates 60 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
60 private System.Timers.Timer m_updateTimer = new System.Timers.Timer(); 61 private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
@@ -73,6 +74,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
73 { 74 {
74 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); 75 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
75 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); 76 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
77 m_reusetextures = appearanceConfig.GetBoolean("ReuseTextures",m_reusetextures);
78
76 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); 79 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
77 } 80 }
78 81
@@ -131,6 +134,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
131 client.OnRequestWearables += Client_OnRequestWearables; 134 client.OnRequestWearables += Client_OnRequestWearables;
132 client.OnSetAppearance += Client_OnSetAppearance; 135 client.OnSetAppearance += Client_OnSetAppearance;
133 client.OnAvatarNowWearing += Client_OnAvatarNowWearing; 136 client.OnAvatarNowWearing += Client_OnAvatarNowWearing;
137 client.OnCachedTextureRequest += Client_OnCachedTextureRequest;
134 } 138 }
135 139
136 #endregion 140 #endregion
@@ -1068,6 +1072,61 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1068 QueueAppearanceSave(client.AgentId); 1072 QueueAppearanceSave(client.AgentId);
1069 } 1073 }
1070 } 1074 }
1075
1076 /// <summary>
1077 /// Respond to the cached textures request from the client
1078 /// </summary>
1079 /// <param name="client"></param>
1080 /// <param name="serial"></param>
1081 /// <param name="cachedTextureRequest"></param>
1082 private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List<CachedTextureRequestArg> cachedTextureRequest)
1083 {
1084 // m_log.WarnFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId);
1085 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
1086
1087 List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>();
1088 foreach (CachedTextureRequestArg request in cachedTextureRequest)
1089 {
1090 UUID texture = UUID.Zero;
1091 int index = request.BakedTextureIndex;
1092
1093 if (m_reusetextures)
1094 {
1095 // this is the most insanely dumb way to do this... however it seems to
1096 // actually work. if the appearance has been reset because wearables have
1097 // changed then the texture entries are zero'd out until the bakes are
1098 // uploaded. on login, if the textures exist in the cache (eg if you logged
1099 // into the simulator recently, then the appearance will pull those and send
1100 // them back in the packet and you won't have to rebake. if the textures aren't
1101 // in the cache then the intial makeroot() call in scenepresence will zero
1102 // them out.
1103 //
1104 // a better solution (though how much better is an open question) is to
1105 // store the hashes in the appearance and compare them. Thats's coming.
1106
1107 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
1108 if (face != null)
1109 texture = face.TextureID;
1110
1111 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
1112 }
1113
1114 CachedTextureResponseArg response = new CachedTextureResponseArg();
1115 response.BakedTextureIndex = index;
1116 response.BakedTextureID = texture;
1117 response.HostName = null;
1118
1119 cachedTextureResponse.Add(response);
1120 }
1121
1122 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial);
1123 // The serial number appears to be used to match requests and responses
1124 // in the texture transaction. We just send back the serial number
1125 // that was provided in the request. The viewer bumps this for us.
1126 client.SendCachedTextureResponse(sp, serial, cachedTextureResponse);
1127 }
1128
1129
1071 #endregion 1130 #endregion
1072 1131
1073 public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction) 1132 public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction)
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 174642d..5cbfec6 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -32,6 +32,7 @@ using log4net;
32using Nini.Config; 32using Nini.Config;
33using Mono.Addins; 33using Mono.Addins;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
@@ -103,6 +104,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
103 104
104 public virtual void RegionLoaded(Scene scene) 105 public virtual void RegionLoaded(Scene scene)
105 { 106 {
107 if (!m_enabled)
108 return;
109
110 ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
111
112 if (featuresModule != null)
113 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
114
106 } 115 }
107 116
108 public virtual void RemoveRegion(Scene scene) 117 public virtual void RemoveRegion(Scene scene)
@@ -372,21 +381,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
372 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, 381 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type,
373 string message, ChatSourceType src, bool ignoreDistance) 382 string message, ChatSourceType src, bool ignoreDistance)
374 { 383 {
375 // don't send chat to child agents 384 if (presence.LifecycleState != ScenePresenceState.Running)
376 if (presence.IsChildAgent) return false; 385 return false;
377
378 Vector3 fromRegionPos = fromPos + regionPos;
379 Vector3 toRegionPos = presence.AbsolutePosition +
380 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
381 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
382 386
383 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); 387 if (!ignoreDistance)
384
385 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
386 type == ChatTypeEnum.Say && dis > m_saydistance ||
387 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
388 { 388 {
389 return false; 389 Vector3 fromRegionPos = fromPos + regionPos;
390 Vector3 toRegionPos = presence.AbsolutePosition +
391 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
392 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
393
394 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
395
396 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
397 type == ChatTypeEnum.Say && dis > m_saydistance ||
398 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
399 {
400 return false;
401 }
390 } 402 }
391 403
392 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView 404 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
@@ -426,5 +438,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
426 Timers.Remove(target); 438 Timers.Remove(target);
427 Timer.Dispose(); 439 Timer.Dispose();
428 } 440 }
441 #region SimulatorFeaturesRequest
442
443 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;
444
445 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
446 {
447 OSD extras = new OSDMap();
448 if (features.ContainsKey("OpenSimExtras"))
449 extras = features["OpenSimExtras"];
450 else
451 features["OpenSimExtras"] = extras;
452
453 if (m_SayRange == null)
454 {
455 // Do this only once
456 m_SayRange = new OSDInteger(m_saydistance);
457 m_WhisperRange = new OSDInteger(m_whisperdistance);
458 m_ShoutRange = new OSDInteger(m_shoutdistance);
459 }
460
461 ((OSDMap)extras)["say-range"] = m_SayRange;
462 ((OSDMap)extras)["whisper-range"] = m_WhisperRange;
463 ((OSDMap)extras)["shout-range"] = m_ShoutRange;
464
465 }
466
467 #endregion
429 } 468 }
430} 469}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 8056030..b693f2d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -371,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
371 foreach (string fid in outstanding) 371 foreach (string fid in outstanding)
372 { 372 {
373 UUID fromAgentID; 373 UUID fromAgentID;
374 string firstname = "Unknown", lastname = "User"; 374 string firstname = "Unknown", lastname = "UserFMSFOIN";
375 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname)) 375 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname))
376 { 376 {
377 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid); 377 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid);
@@ -397,7 +397,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
397 397
398 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 398 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
399 { 399 {
400 first = "Unknown"; last = "User"; 400 first = "Unknown"; last = "UserFMGAI";
401 if (!UUID.TryParse(fid, out agentID)) 401 if (!UUID.TryParse(fid, out agentID))
402 return false; 402 return false;
403 403
@@ -498,6 +498,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
498 498
499 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) 499 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
500 { 500 {
501 //m_log.DebugFormat("[FRIENDS]: Entering StatusNotify for {0}", userID);
502
501 List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend); 503 List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend);
502 List<string> remoteFriendStringIds = new List<string>(); 504 List<string> remoteFriendStringIds = new List<string>();
503 foreach (string friendStringId in friendStringIds) 505 foreach (string friendStringId in friendStringIds)
@@ -523,12 +525,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
523 foreach (PresenceInfo friendSession in friendSessions) 525 foreach (PresenceInfo friendSession in friendSessions)
524 { 526 {
525 // let's guard against sessions-gone-bad 527 // let's guard against sessions-gone-bad
526 if (friendSession.RegionID != UUID.Zero) 528 if (friendSession != null && friendSession.RegionID != UUID.Zero)
527 { 529 {
530 //m_log.DebugFormat("[FRIENDS]: Get region {0}", friendSession.RegionID);
528 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); 531 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
529 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); 532 if (region != null)
530 m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online); 533 {
534 m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online);
535 }
531 } 536 }
537 //else
538 // m_log.DebugFormat("[FRIENDS]: friend session is null or the region is UUID.Zero");
532 } 539 }
533 } 540 }
534 541
@@ -685,7 +692,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
685 // 692 //
686 693
687 // Try local 694 // Try local
688 if (LocalFriendshipTerminated(exfriendID)) 695 if (LocalFriendshipTerminated(client.AgentId, exfriendID))
689 return; 696 return;
690 697
691 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() }); 698 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() });
@@ -827,13 +834,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
827 return false; 834 return false;
828 } 835 }
829 836
830 public bool LocalFriendshipTerminated(UUID exfriendID) 837 public bool LocalFriendshipTerminated(UUID userID, UUID exfriendID)
831 { 838 {
832 IClientAPI friendClient = LocateClientObject(exfriendID); 839 IClientAPI friendClient = LocateClientObject(exfriendID);
833 if (friendClient != null) 840 if (friendClient != null)
834 { 841 {
835 // the friend in this sim as root agent 842 // the friend in this sim as root agent
836 friendClient.SendTerminateFriend(exfriendID); 843 friendClient.SendTerminateFriend(userID);
837 // update local cache 844 // update local cache
838 RecacheFriends(friendClient); 845 RecacheFriends(friendClient);
839 // we're done 846 // we're done
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 637beef..ff87ece 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -42,19 +42,27 @@ using log4net;
42 42
43namespace OpenSim.Region.CoreModules.Avatar.Friends 43namespace OpenSim.Region.CoreModules.Avatar.Friends
44{ 44{
45 public class FriendsRequestHandler : BaseStreamHandler 45 public class FriendsRequestHandler : BaseStreamHandlerBasicDOSProtector
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private FriendsModule m_FriendsModule; 49 private FriendsModule m_FriendsModule;
50 50
51 public FriendsRequestHandler(FriendsModule fmodule) 51 public FriendsRequestHandler(FriendsModule fmodule)
52 : base("POST", "/friends") 52 : base("POST", "/friends", new BasicDosProtectorOptions()
53 {
54 AllowXForwardedFor = true,
55 ForgetTimeSpan = TimeSpan.FromMinutes(2),
56 MaxRequestsInTimeframe = 20,
57 ReportingName = "FRIENDSDOSPROTECTOR",
58 RequestTimeSpan = TimeSpan.FromSeconds(5),
59 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
60 })
53 { 61 {
54 m_FriendsModule = fmodule; 62 m_FriendsModule = fmodule;
55 } 63 }
56 64
57 public override byte[] Handle( 65 protected override byte[] ProcessRequest(
58 string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 67 {
60 StreamReader sr = new StreamReader(requestData); 68 StreamReader sr = new StreamReader(requestData);
@@ -193,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
193 if (!UUID.TryParse(request["ToID"].ToString(), out toID)) 201 if (!UUID.TryParse(request["ToID"].ToString(), out toID))
194 return FailureResult(); 202 return FailureResult();
195 203
196 if (m_FriendsModule.LocalFriendshipTerminated(toID)) 204 if (m_FriendsModule.LocalFriendshipTerminated(fromID, toID))
197 return SuccessResult(); 205 return SuccessResult();
198 206
199 return FailureResult(); 207 return FailureResult();
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index bf5c0bb..d00945e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -183,6 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
183 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp)) 183 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp))
184 { 184 {
185 IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>(); 185 IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
186 m_log.DebugFormat("[HGFRIENDS MODULE]: caching {0}", finfo.Friend);
186 uMan.AddUser(id, url + ";" + first + " " + last); 187 uMan.AddUser(id, url + ";" + first + " " + last);
187 } 188 }
188 } 189 }
@@ -251,7 +252,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
251 252
252 protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) 253 protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
253 { 254 {
254// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID); 255 //m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID);
255 256
256 // First, let's divide the friends on a per-domain basis 257 // First, let's divide the friends on a per-domain basis
257 Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>(); 258 Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
@@ -293,7 +294,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
293 294
294 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 295 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
295 { 296 {
296 first = "Unknown"; last = "User"; 297 first = "Unknown"; last = "UserHGGAI";
297 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last)) 298 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
298 return true; 299 return true;
299 300
@@ -349,7 +350,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
349 350
350 public override FriendInfo[] GetFriendsFromService(IClientAPI client) 351 public override FriendInfo[] GetFriendsFromService(IClientAPI client)
351 { 352 {
352// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetFriendsFromService for {0}", client.Name); 353 // m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetFriendsFromService for {0}", client.Name);
353 Boolean agentIsLocal = true; 354 Boolean agentIsLocal = true;
354 if (UserManagementModule != null) 355 if (UserManagementModule != null)
355 agentIsLocal = UserManagementModule.IsLocalGridUser(client.AgentId); 356 agentIsLocal = UserManagementModule.IsLocalGridUser(client.AgentId);
@@ -362,13 +363,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
362 AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); 363 AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
363 if (agentClientCircuit != null) 364 if (agentClientCircuit != null)
364 { 365 {
365 //[XXX] string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); 366 // Note that this is calling a different interface than base; this one calls with a string param!
366
367 finfos = FriendsService.GetFriends(client.AgentId.ToString()); 367 finfos = FriendsService.GetFriends(client.AgentId.ToString());
368 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, client.AgentId.ToString()); 368 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, client.AgentId.ToString());
369 } 369 }
370 370
371// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name); 371 // m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name);
372 372
373 return finfos; 373 return finfos;
374 } 374 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index fa8c3f3..adb838c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -26,27 +26,25 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
30using Nini.Config;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Region.Framework.Interfaces;
35using System;
36using System.Reflection;
37using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
38using System.Collections.Specialized; 31using System.Collections.Specialized;
39using System.Reflection;
40using System.IO; 32using System.IO;
33using System.Reflection;
41using System.Web; 34using System.Web;
42using System.Xml; 35using System.Xml;
43using log4net; 36using log4net;
44using Mono.Addins; 37using Mono.Addins;
38using Nini.Config;
39using OpenMetaverse;
45using OpenMetaverse.Messages.Linden; 40using OpenMetaverse.Messages.Linden;
46using OpenMetaverse.StructuredData; 41using OpenMetaverse.StructuredData;
42using OpenSim.Framework;
47using OpenSim.Framework.Capabilities; 43using OpenSim.Framework.Capabilities;
48using OpenSim.Framework.Servers; 44using OpenSim.Framework.Servers;
49using OpenSim.Framework.Servers.HttpServer; 45using OpenSim.Framework.Servers.HttpServer;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Framework.Interfaces;
50using Caps = OpenSim.Framework.Capabilities.Caps; 48using Caps = OpenSim.Framework.Capabilities.Caps;
51using OSDArray = OpenMetaverse.StructuredData.OSDArray; 49using OSDArray = OpenMetaverse.StructuredData.OSDArray;
52using OSDMap = OpenMetaverse.StructuredData.OSDMap; 50using OSDMap = OpenMetaverse.StructuredData.OSDMap;
@@ -127,9 +125,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
127 { 125 {
128 string uri = "/CAPS/" + UUID.Random(); 126 string uri = "/CAPS/" + UUID.Random();
129 127
130 caps.RegisterHandler("UntrustedSimulatorMessage", 128 caps.RegisterHandler(
131 new RestStreamHandler("POST", uri, 129 "UntrustedSimulatorMessage",
132 HandleUntrustedSimulatorMessage)); 130 new RestStreamHandler("POST", uri, HandleUntrustedSimulatorMessage, "UntrustedSimulatorMessage", null));
133 } 131 }
134 132
135 private string HandleUntrustedSimulatorMessage(string request, 133 private string HandleUntrustedSimulatorMessage(string request,
@@ -278,7 +276,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
278 if (sp.IsChildAgent) 276 if (sp.IsChildAgent)
279 return; 277 return;
280 sp.ControllingClient.Kick(reason); 278 sp.ControllingClient.Kick(reason);
281 sp.Scene.IncomingCloseAgent(sp.UUID, true); 279 sp.Scene.CloseAgent(sp.UUID, true);
282 } 280 }
283 281
284 private void OnIncomingInstantMessage(GridInstantMessage msg) 282 private void OnIncomingInstantMessage(GridInstantMessage msg)
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 1627f6c..b321adb 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -392,7 +392,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
392 gim.fromAgentName = fromAgentName; 392 gim.fromAgentName = fromAgentName;
393 gim.fromGroup = fromGroup; 393 gim.fromGroup = fromGroup;
394 gim.imSessionID = imSessionID.Guid; 394 gim.imSessionID = imSessionID.Guid;
395 gim.RegionID = UUID.Zero.Guid; // RegionID.Guid; 395 gim.RegionID = RegionID.Guid;
396 gim.timestamp = timestamp; 396 gim.timestamp = timestamp;
397 gim.toAgentID = toAgentID.Guid; 397 gim.toAgentID = toAgentID.Guid;
398 gim.message = message; 398 gim.message = message;
@@ -728,7 +728,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
728 gim["position_x"] = msg.Position.X.ToString(); 728 gim["position_x"] = msg.Position.X.ToString();
729 gim["position_y"] = msg.Position.Y.ToString(); 729 gim["position_y"] = msg.Position.Y.ToString();
730 gim["position_z"] = msg.Position.Z.ToString(); 730 gim["position_z"] = msg.Position.Z.ToString();
731 gim["region_id"] = msg.RegionID.ToString(); 731 gim["region_id"] = new UUID(msg.RegionID).ToString();
732 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); 732 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
733 if (m_MessageKey != String.Empty) 733 if (m_MessageKey != String.Empty)
734 gim["message_key"] = m_MessageKey; 734 gim["message_key"] = m_MessageKey;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 659b178..5a8544e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -67,10 +67,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
67 /// </summary> 67 /// </summary>
68 protected bool m_merge; 68 protected bool m_merge;
69 69
70 /// <value> 70 protected IInventoryService m_InventoryService;
71 /// We only use this to request modules 71 protected IAssetService m_AssetService;
72 /// </value> 72 protected IUserAccountService m_UserAccountService;
73 protected Scene m_scene;
74 73
75 /// <value> 74 /// <value>
76 /// The stream from which the inventory archive will be loaded. 75 /// The stream from which the inventory archive will be loaded.
@@ -118,9 +117,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
118 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>(); 117 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>();
119 118
120 public InventoryArchiveReadRequest( 119 public InventoryArchiveReadRequest(
121 Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge) 120 IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge)
122 : this( 121 : this(
123 scene, 122 inv,
123 assets,
124 uacc,
124 userInfo, 125 userInfo,
125 invPath, 126 invPath,
126 new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress), 127 new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress),
@@ -129,9 +130,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
129 } 130 }
130 131
131 public InventoryArchiveReadRequest( 132 public InventoryArchiveReadRequest(
132 Scene scene, UserAccount userInfo, string invPath, Stream loadStream, bool merge) 133 IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, Stream loadStream, bool merge)
133 { 134 {
134 m_scene = scene; 135 m_InventoryService = inv;
136 m_AssetService = assets;
137 m_UserAccountService = uacc;
135 m_merge = merge; 138 m_merge = merge;
136 m_userInfo = userInfo; 139 m_userInfo = userInfo;
137 m_invPath = invPath; 140 m_invPath = invPath;
@@ -162,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
162 165
163 List<InventoryFolderBase> folderCandidates 166 List<InventoryFolderBase> folderCandidates
164 = InventoryArchiveUtils.FindFoldersByPath( 167 = InventoryArchiveUtils.FindFoldersByPath(
165 m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); 168 m_InventoryService, m_userInfo.PrincipalID, m_invPath);
166 169
167 if (folderCandidates.Count == 0) 170 if (folderCandidates.Count == 0)
168 { 171 {
@@ -297,7 +300,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
297 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); 300 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
298 List<InventoryFolderBase> folderCandidates 301 List<InventoryFolderBase> folderCandidates
299 = InventoryArchiveUtils.FindFoldersByPath( 302 = InventoryArchiveUtils.FindFoldersByPath(
300 m_scene.InventoryService, m_userInfo.PrincipalID, plainPath); 303 m_InventoryService, m_userInfo.PrincipalID, plainPath);
301 304
302 if (folderCandidates.Count != 0) 305 if (folderCandidates.Count != 0)
303 { 306 {
@@ -380,7 +383,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
380 = new InventoryFolderBase( 383 = new InventoryFolderBase(
381 newFolderId, newFolderName, m_userInfo.PrincipalID, 384 newFolderId, newFolderName, m_userInfo.PrincipalID,
382 (short)AssetType.Unknown, destFolder.ID, 1); 385 (short)AssetType.Unknown, destFolder.ID, 1);
383 m_scene.InventoryService.AddFolder(destFolder); 386 m_InventoryService.AddFolder(destFolder);
384 387
385 // Record that we have now created this folder 388 // Record that we have now created this folder
386 iarPathExisting += rawDirsToCreate[i] + "/"; 389 iarPathExisting += rawDirsToCreate[i] + "/";
@@ -406,7 +409,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
406 // Don't use the item ID that's in the file 409 // Don't use the item ID that's in the file
407 item.ID = UUID.Random(); 410 item.ID = UUID.Random();
408 411
409 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.UserAccountService); 412 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_UserAccountService);
410 if (UUID.Zero != ospResolvedId) // The user exists in this grid 413 if (UUID.Zero != ospResolvedId) // The user exists in this grid
411 { 414 {
412// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId); 415// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId);
@@ -418,7 +421,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
418 item.CreatorId = ospResolvedId.ToString(); 421 item.CreatorId = ospResolvedId.ToString();
419 item.CreatorData = string.Empty; 422 item.CreatorData = string.Empty;
420 } 423 }
421 else if (item.CreatorData == null || item.CreatorData == String.Empty) 424 else if (string.IsNullOrEmpty(item.CreatorData))
422 { 425 {
423 item.CreatorId = m_userInfo.PrincipalID.ToString(); 426 item.CreatorId = m_userInfo.PrincipalID.ToString();
424// item.CreatorIdAsUuid = new UUID(item.CreatorId); 427// item.CreatorIdAsUuid = new UUID(item.CreatorId);
@@ -436,7 +439,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
436 // relying on native tar tools. 439 // relying on native tar tools.
437 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid; 440 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid;
438 441
439 m_scene.AddInventoryItem(item); 442 if (!m_InventoryService.AddItem(item))
443 m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.Name, item.Folder);
440 444
441 return item; 445 return item;
442 } 446 }
@@ -518,7 +522,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
518 522
519 foreach (SceneObjectGroup sog in sceneObjects) 523 foreach (SceneObjectGroup sog in sceneObjects)
520 foreach (SceneObjectPart sop in sog.Parts) 524 foreach (SceneObjectPart sop in sog.Parts)
521 if (sop.CreatorData == null || sop.CreatorData == "") 525 if (string.IsNullOrEmpty(sop.CreatorData))
522 sop.CreatorID = m_creatorIdForAssetId[assetId]; 526 sop.CreatorID = m_creatorIdForAssetId[assetId];
523 527
524 if (coa != null) 528 if (coa != null)
@@ -533,7 +537,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
533 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString()); 537 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString());
534 asset.Data = data; 538 asset.Data = data;
535 539
536 m_scene.AssetService.Store(asset); 540 m_AssetService.Store(asset);
537 541
538 return true; 542 return true;
539 } 543 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 4ec8ae7..4292719 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -78,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
78 /// <value> 78 /// <value>
79 /// Used to collect the uuids of the assets that we need to save into the archive 79 /// Used to collect the uuids of the assets that we need to save into the archive
80 /// </value> 80 /// </value>
81 protected Dictionary<UUID, AssetType> m_assetUuids = new Dictionary<UUID, AssetType>(); 81 protected Dictionary<UUID, sbyte> m_assetUuids = new Dictionary<UUID, sbyte>();
82 82
83 /// <value> 83 /// <value>
84 /// Used to collect the uuids of the users that we need to save into the archive 84 /// Used to collect the uuids of the users that we need to save into the archive
@@ -187,7 +187,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
187 187
188 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset 188 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset
189 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) 189 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
190 m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); 190 m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (sbyte)inventoryItem.AssetType, m_assetUuids);
191 } 191 }
192 192
193 /// <summary> 193 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index f4f9e2d..ea660bd 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -294,7 +294,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
294 294
295 try 295 try
296 { 296 {
297 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream, merge); 297 request = new InventoryArchiveReadRequest(m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadStream, merge);
298 } 298 }
299 catch (EntryPointNotFoundException e) 299 catch (EntryPointNotFoundException e)
300 { 300 {
@@ -342,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
342 342
343 try 343 try
344 { 344 {
345 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge); 345 request = new InventoryArchiveReadRequest(m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadPath, merge);
346 } 346 }
347 catch (EntryPointNotFoundException e) 347 catch (EntryPointNotFoundException e)
348 { 348 {
@@ -538,7 +538,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
538 } 538 }
539 catch (Exception e) 539 catch (Exception e)
540 { 540 {
541 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message); 541 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e);
542 return null; 542 return null;
543 } 543 }
544 */ 544 */
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
index 95f562e..08f199a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
@@ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
229 229
230 { 230 {
231 // Test replication of path1 231 // Test replication of path1
232 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) 232 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
233 .ReplicateArchivePathToUserInventory( 233 .ReplicateArchivePathToUserInventory(
234 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 234 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
235 foldersCreated, nodesLoaded); 235 foldersCreated, nodesLoaded);
@@ -246,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
246 246
247 { 247 {
248 // Test replication of path2 248 // Test replication of path2
249 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) 249 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
250 .ReplicateArchivePathToUserInventory( 250 .ReplicateArchivePathToUserInventory(
251 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 251 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
252 foldersCreated, nodesLoaded); 252 foldersCreated, nodesLoaded);
@@ -291,8 +291,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
291 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 291 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
292 292
293 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 293 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
294 294
295 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) 295 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
296 .ReplicateArchivePathToUserInventory( 296 .ReplicateArchivePathToUserInventory(
297 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 297 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
298 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 298 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
@@ -342,8 +342,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
342 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 342 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
343 343
344 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 344 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
345 345
346 new InventoryArchiveReadRequest(scene, ua1, folder1ExistingName, (Stream)null, true) 346 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, folder1ExistingName, (Stream)null, true)
347 .ReplicateArchivePathToUserInventory( 347 .ReplicateArchivePathToUserInventory(
348 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 348 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
349 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 349 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
index 5e7e24c..b85739e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
@@ -86,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
86 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 86 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
87 87
88 InventoryArchiveReadRequest iarr 88 InventoryArchiveReadRequest iarr
89 = new InventoryArchiveReadRequest(null, null, null, (Stream)null, false); 89 = new InventoryArchiveReadRequest(null, null, null, null, null, (Stream)null, false);
90 iarr.LoadControlFile(filePath, data); 90 iarr.LoadControlFile(filePath, data);
91 91
92 Assert.That(iarr.ControlFileLoaded, Is.True); 92 Assert.That(iarr.ControlFileLoaded, Is.True);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index f122d00..03aaaac 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -47,10 +47,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
47 47
48 /// <summary> 48 /// <summary>
49 private List<Scene> m_Scenelist = new List<Scene>(); 49 private List<Scene> m_Scenelist = new List<Scene>();
50// private Dictionary<UUID, Scene> m_AgentRegions =
51// new Dictionary<UUID, Scene>();
52 50
53 private IMessageTransferModule m_TransferModule = null; 51 private IMessageTransferModule m_TransferModule;
54 private bool m_Enabled = true; 52 private bool m_Enabled = true;
55 53
56 #region Region Module interface 54 #region Region Module interface
@@ -81,9 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
81// scene.RegisterModuleInterface<IInventoryTransferModule>(this); 79// scene.RegisterModuleInterface<IInventoryTransferModule>(this);
82 80
83 scene.EventManager.OnNewClient += OnNewClient; 81 scene.EventManager.OnNewClient += OnNewClient;
84// scene.EventManager.OnClientClosed += ClientLoggedOut;
85 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 82 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
86// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
87 } 83 }
88 84
89 public void RegionLoaded(Scene scene) 85 public void RegionLoaded(Scene scene)
@@ -96,11 +92,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
96 m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only"); 92 m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only");
97 m_Enabled = false; 93 m_Enabled = false;
98 94
99 m_Scenelist.Clear(); 95// m_Scenelist.Clear();
100 scene.EventManager.OnNewClient -= OnNewClient; 96// scene.EventManager.OnNewClient -= OnNewClient;
101// scene.EventManager.OnClientClosed -= ClientLoggedOut;
102 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 97 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
103// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
104 } 98 }
105 } 99 }
106 } 100 }
@@ -108,9 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
108 public void RemoveRegion(Scene scene) 102 public void RemoveRegion(Scene scene)
109 { 103 {
110 scene.EventManager.OnNewClient -= OnNewClient; 104 scene.EventManager.OnNewClient -= OnNewClient;
111// scene.EventManager.OnClientClosed -= ClientLoggedOut;
112 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 105 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
113// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
114 m_Scenelist.Remove(scene); 106 m_Scenelist.Remove(scene);
115 } 107 }
116 108
@@ -139,11 +131,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
139 // Inventory giving is conducted via instant message 131 // Inventory giving is conducted via instant message
140 client.OnInstantMessage += OnInstantMessage; 132 client.OnInstantMessage += OnInstantMessage;
141 } 133 }
142
143// protected void OnSetRootAgentScene(UUID id, Scene scene)
144// {
145// m_AgentRegions[id] = scene;
146// }
147 134
148 private Scene FindClientScene(UUID agentId) 135 private Scene FindClientScene(UUID agentId)
149 { 136 {
@@ -162,8 +149,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
162 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 149 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
163 { 150 {
164// m_log.DebugFormat( 151// m_log.DebugFormat(
165// "[INVENTORY TRANSFER]: {0} IM type received from {1}", 152// "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}",
166// (InstantMessageDialog)im.dialog, client.Name); 153// (InstantMessageDialog)im.dialog, client.Name,
154// im.fromAgentID, im.fromAgentName, im.toAgentID);
167 155
168 Scene scene = FindClientScene(client.AgentId); 156 Scene scene = FindClientScene(client.AgentId);
169 157
@@ -188,9 +176,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
188 { 176 {
189 UUID folderID = new UUID(im.binaryBucket, 1); 177 UUID folderID = new UUID(im.binaryBucket, 1);
190 178
191 m_log.DebugFormat("[INVENTORY TRANSFER]: Inserting original folder {0} "+ 179 m_log.DebugFormat(
192 "into agent {1}'s inventory", 180 "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory",
193 folderID, new UUID(im.toAgentID)); 181 folderID, new UUID(im.toAgentID));
194 182
195 InventoryFolderBase folderCopy 183 InventoryFolderBase folderCopy
196 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero); 184 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero);
@@ -213,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
213 user.ControllingClient.SendBulkUpdateInventory(folderCopy); 201 user.ControllingClient.SendBulkUpdateInventory(folderCopy);
214 202
215 // HACK!! 203 // HACK!!
216 // Insert the ID of the copied item into the IM so that we know which item to move to trash if it 204 // Insert the ID of the copied folder into the IM so that we know which item to move to trash if it
217 // is rejected. 205 // is rejected.
218 // XXX: This is probably a misuse of the session ID slot. 206 // XXX: This is probably a misuse of the session ID slot.
219 im.imSessionID = copyID.Guid; 207 im.imSessionID = copyID.Guid;
@@ -425,7 +413,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
425 { 413 {
426 folder = new InventoryFolderBase(inventoryID, client.AgentId); 414 folder = new InventoryFolderBase(inventoryID, client.AgentId);
427 folder = invService.GetFolder(folder); 415 folder = invService.GetFolder(folder);
428 416
429 if (folder != null & trashFolder != null) 417 if (folder != null & trashFolder != null)
430 { 418 {
431 previousParentFolderID = folder.ParentID; 419 previousParentFolderID = folder.ParentID;
@@ -477,76 +465,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
477 } 465 }
478 } 466 }
479 467
480// public bool NeedSceneCacheClear(UUID agentID, Scene scene)
481// {
482// if (!m_AgentRegions.ContainsKey(agentID))
483// {
484// // Since we can get here two ways, we need to scan
485// // the scenes here. This is somewhat more expensive
486// // but helps avoid a nasty bug
487// //
488//
489// foreach (Scene s in m_Scenelist)
490// {
491// ScenePresence presence;
492//
493// if (s.TryGetScenePresence(agentID, out presence))
494// {
495// // If the agent is in this scene, then we
496// // are being called twice in a single
497// // teleport. This is wasteful of cycles
498// // but harmless due to this 2nd level check
499// //
500// // If the agent is found in another scene
501// // then the list wasn't current
502// //
503// // If the agent is totally unknown, then what
504// // are we even doing here??
505// //
506// if (s == scene)
507// {
508// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
509// return true;
510// }
511// else
512// {
513// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
514// return false;
515// }
516// }
517// }
518// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
519// return true;
520// }
521//
522// // The agent is left in current Scene, so we must be
523// // going to another instance
524// //
525// if (m_AgentRegions[agentID] == scene)
526// {
527// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
528// m_AgentRegions.Remove(agentID);
529// return true;
530// }
531//
532// // Another region has claimed the agent
533// //
534// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
535// return false;
536// }
537//
538// public void ClientLoggedOut(UUID agentID, Scene scene)
539// {
540// if (m_AgentRegions.ContainsKey(agentID))
541// m_AgentRegions.Remove(agentID);
542// }
543
544 /// <summary> 468 /// <summary>
545 /// 469 ///
546 /// </summary> 470 /// </summary>
547 /// <param name="msg"></param> 471 /// <param name="im"></param>
548 private void OnGridInstantMessage(GridInstantMessage im) 472 private void OnGridInstantMessage(GridInstantMessage im)
549 { 473 {
474 // Check if it's a type of message that we should handle
475 if (!((im.dialog == (byte) InstantMessageDialog.InventoryOffered)
476 || (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
477 || (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
478 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)))
479 return;
480
481 m_log.DebugFormat(
482 "[INVENTORY TRANSFER]: {0} IM type received from grid. From={1} ({2}), To={3}",
483 (InstantMessageDialog)im.dialog, im.fromAgentID, im.fromAgentName, im.toAgentID);
484
550 // Check if this is ours to handle 485 // Check if this is ours to handle
551 // 486 //
552 Scene scene = FindClientScene(new UUID(im.toAgentID)); 487 Scene scene = FindClientScene(new UUID(im.toAgentID));
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
new file mode 100644
index 0000000..162a0c3
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
@@ -0,0 +1,449 @@
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.Config;
32using Nini.Config;
33using NUnit.Framework;
34using OpenMetaverse;
35using OpenMetaverse.Assets;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.Avatar.Inventory.Transfer;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock;
43
44namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
45{
46 [TestFixture]
47 public class InventoryTransferModuleTests : OpenSimTestCase
48 {
49 protected TestScene m_scene;
50
51 [SetUp]
52 public override void SetUp()
53 {
54 base.SetUp();
55
56 IConfigSource config = new IniConfigSource();
57 config.AddConfig("Messaging");
58 config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule");
59
60 m_scene = new SceneHelpers().SetupScene();
61 SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule());
62 }
63
64 [Test]
65 public void TestAcceptGivenItem()
66 {
67// TestHelpers.EnableLogging();
68
69 UUID initialSessionId = TestHelpers.ParseTail(0x10);
70 UUID itemId = TestHelpers.ParseTail(0x100);
71 UUID assetId = TestHelpers.ParseTail(0x200);
72
73 UserAccount ua1
74 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
75 UserAccount ua2
76 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
77
78 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
79 TestClient giverClient = (TestClient)giverSp.ControllingClient;
80
81 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
82 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
83
84 // Create the object to test give
85 InventoryItemBase originalItem
86 = UserInventoryHelpers.CreateInventoryItem(
87 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
88
89 byte[] giveImBinaryBucket = new byte[17];
90 byte[] itemIdBytes = itemId.GetBytes();
91 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
92
93 GridInstantMessage giveIm
94 = new GridInstantMessage(
95 m_scene,
96 giverSp.UUID,
97 giverSp.Name,
98 receiverSp.UUID,
99 (byte)InstantMessageDialog.InventoryOffered,
100 false,
101 "inventory offered msg",
102 initialSessionId,
103 false,
104 Vector3.Zero,
105 giveImBinaryBucket,
106 true);
107
108 giverClient.HandleImprovedInstantMessage(giveIm);
109
110 // These details might not all be correct.
111 GridInstantMessage acceptIm
112 = new GridInstantMessage(
113 m_scene,
114 receiverSp.UUID,
115 receiverSp.Name,
116 giverSp.UUID,
117 (byte)InstantMessageDialog.InventoryAccepted,
118 false,
119 "inventory accepted msg",
120 initialSessionId,
121 false,
122 Vector3.Zero,
123 null,
124 true);
125
126 receiverClient.HandleImprovedInstantMessage(acceptIm);
127
128 // Test for item remaining in the giver's inventory (here we assume a copy item)
129 // TODO: Test no-copy items.
130 InventoryItemBase originalItemAfterGive
131 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
132
133 Assert.That(originalItemAfterGive, Is.Not.Null);
134 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
135
136 // Test for item successfully making it into the receiver's inventory
137 InventoryItemBase receivedItem
138 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj");
139
140 Assert.That(receivedItem, Is.Not.Null);
141 Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID));
142
143 // Test that on a delete, item still exists and is accessible for the giver.
144 m_scene.InventoryService.DeleteItems(receiverSp.UUID, new List<UUID>() { receivedItem.ID });
145
146 InventoryItemBase originalItemAfterDelete
147 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
148
149 Assert.That(originalItemAfterDelete, Is.Not.Null);
150
151 // TODO: Test scenario where giver deletes their item first.
152 }
153
154 /// <summary>
155 /// Test user rejection of a given item.
156 /// </summary>
157 /// <remarks>
158 /// A rejected item still ends up in the user's trash folder.
159 /// </remarks>
160 [Test]
161 public void TestRejectGivenItem()
162 {
163// TestHelpers.EnableLogging();
164
165 UUID initialSessionId = TestHelpers.ParseTail(0x10);
166 UUID itemId = TestHelpers.ParseTail(0x100);
167 UUID assetId = TestHelpers.ParseTail(0x200);
168
169 UserAccount ua1
170 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
171 UserAccount ua2
172 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
173
174 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
175 TestClient giverClient = (TestClient)giverSp.ControllingClient;
176
177 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
178 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
179
180 // Create the object to test give
181 InventoryItemBase originalItem
182 = UserInventoryHelpers.CreateInventoryItem(
183 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
184
185 GridInstantMessage receivedIm = null;
186 receiverClient.OnReceivedInstantMessage += im => receivedIm = im;
187
188 byte[] giveImBinaryBucket = new byte[17];
189 byte[] itemIdBytes = itemId.GetBytes();
190 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
191
192 GridInstantMessage giveIm
193 = new GridInstantMessage(
194 m_scene,
195 giverSp.UUID,
196 giverSp.Name,
197 receiverSp.UUID,
198 (byte)InstantMessageDialog.InventoryOffered,
199 false,
200 "inventory offered msg",
201 initialSessionId,
202 false,
203 Vector3.Zero,
204 giveImBinaryBucket,
205 true);
206
207 giverClient.HandleImprovedInstantMessage(giveIm);
208
209 // These details might not all be correct.
210 // Session ID is now the created item ID (!)
211 GridInstantMessage rejectIm
212 = new GridInstantMessage(
213 m_scene,
214 receiverSp.UUID,
215 receiverSp.Name,
216 giverSp.UUID,
217 (byte)InstantMessageDialog.InventoryDeclined,
218 false,
219 "inventory declined msg",
220 new UUID(receivedIm.imSessionID),
221 false,
222 Vector3.Zero,
223 null,
224 true);
225
226 receiverClient.HandleImprovedInstantMessage(rejectIm);
227
228 // Test for item remaining in the giver's inventory (here we assume a copy item)
229 // TODO: Test no-copy items.
230 InventoryItemBase originalItemAfterGive
231 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
232
233 Assert.That(originalItemAfterGive, Is.Not.Null);
234 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
235
236 // Test for item successfully making it into the receiver's inventory
237 InventoryItemBase receivedItem
238 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj");
239
240 InventoryFolderBase trashFolder
241 = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, AssetType.TrashFolder);
242
243 Assert.That(receivedItem, Is.Not.Null);
244 Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID));
245 Assert.That(receivedItem.Folder, Is.EqualTo(trashFolder.ID));
246
247 // Test that on a delete, item still exists and is accessible for the giver.
248 m_scene.InventoryService.PurgeFolder(trashFolder);
249
250 InventoryItemBase originalItemAfterDelete
251 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
252
253 Assert.That(originalItemAfterDelete, Is.Not.Null);
254 }
255
256 [Test]
257 public void TestAcceptGivenFolder()
258 {
259 TestHelpers.InMethod();
260// TestHelpers.EnableLogging();
261
262 UUID initialSessionId = TestHelpers.ParseTail(0x10);
263 UUID folderId = TestHelpers.ParseTail(0x100);
264
265 UserAccount ua1
266 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
267 UserAccount ua2
268 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
269
270 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
271 TestClient giverClient = (TestClient)giverSp.ControllingClient;
272
273 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
274 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
275
276 InventoryFolderBase originalFolder
277 = UserInventoryHelpers.CreateInventoryFolder(
278 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
279
280 byte[] giveImBinaryBucket = new byte[17];
281 giveImBinaryBucket[0] = (byte)AssetType.Folder;
282 byte[] itemIdBytes = folderId.GetBytes();
283 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
284
285 GridInstantMessage giveIm
286 = new GridInstantMessage(
287 m_scene,
288 giverSp.UUID,
289 giverSp.Name,
290 receiverSp.UUID,
291 (byte)InstantMessageDialog.InventoryOffered,
292 false,
293 "inventory offered msg",
294 initialSessionId,
295 false,
296 Vector3.Zero,
297 giveImBinaryBucket,
298 true);
299
300 giverClient.HandleImprovedInstantMessage(giveIm);
301
302 // These details might not all be correct.
303 GridInstantMessage acceptIm
304 = new GridInstantMessage(
305 m_scene,
306 receiverSp.UUID,
307 receiverSp.Name,
308 giverSp.UUID,
309 (byte)InstantMessageDialog.InventoryAccepted,
310 false,
311 "inventory accepted msg",
312 initialSessionId,
313 false,
314 Vector3.Zero,
315 null,
316 true);
317
318 receiverClient.HandleImprovedInstantMessage(acceptIm);
319
320 // Test for item remaining in the giver's inventory (here we assume a copy item)
321 // TODO: Test no-copy items.
322 InventoryFolderBase originalFolderAfterGive
323 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
324
325 Assert.That(originalFolderAfterGive, Is.Not.Null);
326 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
327
328 // Test for item successfully making it into the receiver's inventory
329 InventoryFolderBase receivedFolder
330 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1");
331
332 Assert.That(receivedFolder, Is.Not.Null);
333 Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID));
334
335 // Test that on a delete, item still exists and is accessible for the giver.
336 m_scene.InventoryService.DeleteFolders(receiverSp.UUID, new List<UUID>() { receivedFolder.ID });
337
338 InventoryFolderBase originalFolderAfterDelete
339 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
340
341 Assert.That(originalFolderAfterDelete, Is.Not.Null);
342
343 // TODO: Test scenario where giver deletes their item first.
344 }
345
346 /// <summary>
347 /// Test user rejection of a given item.
348 /// </summary>
349 /// <remarks>
350 /// A rejected item still ends up in the user's trash folder.
351 /// </remarks>
352 [Test]
353 public void TestRejectGivenFolder()
354 {
355 TestHelpers.InMethod();
356// TestHelpers.EnableLogging();
357
358 UUID initialSessionId = TestHelpers.ParseTail(0x10);
359 UUID folderId = TestHelpers.ParseTail(0x100);
360
361 UserAccount ua1
362 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
363 UserAccount ua2
364 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
365
366 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
367 TestClient giverClient = (TestClient)giverSp.ControllingClient;
368
369 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
370 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
371
372 // Create the folder to test give
373 InventoryFolderBase originalFolder
374 = UserInventoryHelpers.CreateInventoryFolder(
375 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
376
377 GridInstantMessage receivedIm = null;
378 receiverClient.OnReceivedInstantMessage += im => receivedIm = im;
379
380 byte[] giveImBinaryBucket = new byte[17];
381 giveImBinaryBucket[0] = (byte)AssetType.Folder;
382 byte[] itemIdBytes = folderId.GetBytes();
383 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
384
385 GridInstantMessage giveIm
386 = new GridInstantMessage(
387 m_scene,
388 giverSp.UUID,
389 giverSp.Name,
390 receiverSp.UUID,
391 (byte)InstantMessageDialog.InventoryOffered,
392 false,
393 "inventory offered msg",
394 initialSessionId,
395 false,
396 Vector3.Zero,
397 giveImBinaryBucket,
398 true);
399
400 giverClient.HandleImprovedInstantMessage(giveIm);
401
402 // These details might not all be correct.
403 // Session ID is now the created item ID (!)
404 GridInstantMessage rejectIm
405 = new GridInstantMessage(
406 m_scene,
407 receiverSp.UUID,
408 receiverSp.Name,
409 giverSp.UUID,
410 (byte)InstantMessageDialog.InventoryDeclined,
411 false,
412 "inventory declined msg",
413 new UUID(receivedIm.imSessionID),
414 false,
415 Vector3.Zero,
416 null,
417 true);
418
419 receiverClient.HandleImprovedInstantMessage(rejectIm);
420
421 // Test for item remaining in the giver's inventory (here we assume a copy item)
422 // TODO: Test no-copy items.
423 InventoryFolderBase originalFolderAfterGive
424 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
425
426 Assert.That(originalFolderAfterGive, Is.Not.Null);
427 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
428
429 // Test for folder successfully making it into the receiver's inventory
430 InventoryFolderBase receivedFolder
431 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1");
432
433 InventoryFolderBase trashFolder
434 = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, AssetType.TrashFolder);
435
436 Assert.That(receivedFolder, Is.Not.Null);
437 Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID));
438 Assert.That(receivedFolder.ParentID, Is.EqualTo(trashFolder.ID));
439
440 // Test that on a delete, item still exists and is accessible for the giver.
441 m_scene.InventoryService.PurgeFolder(trashFolder);
442
443 InventoryFolderBase originalFolderAfterDelete
444 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
445
446 Assert.That(originalFolderAfterDelete, Is.Not.Null);
447 }
448 }
449} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 0c64f19..c517a30 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)presence.AbsolutePosition.Z + 2); 166 (uint)presence.AbsolutePosition.Z + 2);
167 167
168 m_log.DebugFormat("TP invite with message {0}, type {1}", message, lureType); 168 m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType);
169 169
170 GridInstantMessage m; 170 GridInstantMessage m;
171 171
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
index bf24030..2bb24ae 100644
--- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
@@ -57,6 +57,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
57 57
58 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
59 { 59 {
60 if(config.Configs["UserProfiles"] != null)
61 return;
62
60 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); 63 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
61 m_Enabled = true; 64 m_Enabled = true;
62 } 65 }
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
new file mode 100644
index 0000000..d359ebc
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -0,0 +1,1343 @@
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.Text;
31using System.Collections;
32using System.Collections.Generic;
33using System.Globalization;
34using System.Net;
35using System.Net.Sockets;
36using System.Reflection;
37using System.Xml;
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40using log4net;
41using Nini.Config;
42using Nwc.XmlRpc;
43using OpenSim.Framework;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Services.Interfaces;
47using Mono.Addins;
48using OpenSim.Services.Connectors.Hypergrid;
49
50namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
51{
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")]
53 public class UserProfileModule : IProfileModule, INonSharedRegionModule
54 {
55 /// <summary>
56 /// Logging
57 /// </summary>
58 static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59
60 // The pair of Dictionaries are used to handle the switching of classified ads
61 // by maintaining a cache of classified id to creator id mappings and an interest
62 // count. The entries are removed when the interest count reaches 0.
63 Dictionary<UUID, UUID> m_classifiedCache = new Dictionary<UUID, UUID>();
64 Dictionary<UUID, int> m_classifiedInterest = new Dictionary<UUID, int>();
65
66 public Scene Scene
67 {
68 get; private set;
69 }
70
71 /// <summary>
72 /// Gets or sets the ConfigSource.
73 /// </summary>
74 /// <value>
75 /// The configuration
76 /// </value>
77 public IConfigSource Config {
78 get;
79 set;
80 }
81
82 /// <summary>
83 /// Gets or sets the URI to the profile server.
84 /// </summary>
85 /// <value>
86 /// The profile server URI.
87 /// </value>
88 public string ProfileServerUri {
89 get;
90 set;
91 }
92
93 IProfileModule ProfileModule
94 {
95 get; set;
96 }
97
98 IUserManagement UserManagementModule
99 {
100 get; set;
101 }
102
103 /// <summary>
104 /// Gets or sets a value indicating whether this
105 /// <see cref="OpenSim.Region.Coremodules.UserProfiles.UserProfileModule"/> is enabled.
106 /// </summary>
107 /// <value>
108 /// <c>true</c> if enabled; otherwise, <c>false</c>.
109 /// </value>
110 public bool Enabled {
111 get;
112 set;
113 }
114
115 #region IRegionModuleBase implementation
116 /// <summary>
117 /// This is called to initialize the region module. For shared modules, this is called exactly once, after
118 /// creating the single (shared) instance. For non-shared modules, this is called once on each instance, after
119 /// the instace for the region has been created.
120 /// </summary>
121 /// <param name='source'>
122 /// Source.
123 /// </param>
124 public void Initialise(IConfigSource source)
125 {
126 Config = source;
127 ReplaceableInterface = typeof(IProfileModule);
128
129 IConfig profileConfig = Config.Configs["UserProfiles"];
130
131 if (profileConfig == null)
132 {
133 m_log.Debug("[PROFILES]: UserProfiles disabled, no configuration");
134 Enabled = false;
135 return;
136 }
137
138 // If we find ProfileURL then we configure for FULL support
139 // else we setup for BASIC support
140 ProfileServerUri = profileConfig.GetString("ProfileServiceURL", "");
141 if (ProfileServerUri == "")
142 {
143 Enabled = false;
144 return;
145 }
146
147 m_log.Debug("[PROFILES]: Full Profiles Enabled");
148 ReplaceableInterface = null;
149 Enabled = true;
150 }
151
152 /// <summary>
153 /// Adds the region.
154 /// </summary>
155 /// <param name='scene'>
156 /// Scene.
157 /// </param>
158 public void AddRegion(Scene scene)
159 {
160 if(!Enabled)
161 return;
162
163 Scene = scene;
164 Scene.RegisterModuleInterface<IProfileModule>(this);
165 Scene.EventManager.OnNewClient += OnNewClient;
166 Scene.EventManager.OnMakeRootAgent += HandleOnMakeRootAgent;
167
168 UserManagementModule = Scene.RequestModuleInterface<IUserManagement>();
169 }
170
171 void HandleOnMakeRootAgent (ScenePresence obj)
172 {
173 if(obj.PresenceType == PresenceType.Npc)
174 return;
175
176 Util.FireAndForget(delegate
177 {
178 GetImageAssets(((IScenePresence)obj).UUID);
179 });
180 }
181
182 /// <summary>
183 /// Removes the region.
184 /// </summary>
185 /// <param name='scene'>
186 /// Scene.
187 /// </param>
188 public void RemoveRegion(Scene scene)
189 {
190 if(!Enabled)
191 return;
192 }
193
194 /// <summary>
195 /// This will be called once for every scene loaded. In a shared module this will be multiple times in one
196 /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion
197 /// has been called in all modules for that scene, providing an opportunity to request another module's
198 /// interface, or hook an event from another module.
199 /// </summary>
200 /// <param name='scene'>
201 /// Scene.
202 /// </param>
203 public void RegionLoaded(Scene scene)
204 {
205 if(!Enabled)
206 return;
207 }
208
209 /// <summary>
210 /// If this returns non-null, it is the type of an interface that this module intends to register. This will
211 /// cause the loader to defer loading of this module until all other modules have been loaded. If no other
212 /// module has registered the interface by then, this module will be activated, else it will remain inactive,
213 /// letting the other module take over. This should return non-null ONLY in modules that are intended to be
214 /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party
215 /// provided modules.
216 /// </summary>
217 /// <value>
218 /// The replaceable interface.
219 /// </value>
220 public Type ReplaceableInterface
221 {
222 get; private set;
223 }
224
225 /// <summary>
226 /// Called as the instance is closed.
227 /// </summary>
228 public void Close()
229 {
230 }
231
232 /// <value>
233 /// The name of the module
234 /// </value>
235 /// <summary>
236 /// Gets the module name.
237 /// </summary>
238 public string Name
239 {
240 get { return "UserProfileModule"; }
241 }
242 #endregion IRegionModuleBase implementation
243
244 #region Region Event Handlers
245 /// <summary>
246 /// Raises the new client event.
247 /// </summary>
248 /// <param name='client'>
249 /// Client.
250 /// </param>
251 void OnNewClient(IClientAPI client)
252 {
253 //Profile
254 client.OnRequestAvatarProperties += RequestAvatarProperties;
255 client.OnUpdateAvatarProperties += AvatarPropertiesUpdate;
256 client.OnAvatarInterestUpdate += AvatarInterestsUpdate;
257
258 // Classifieds
259 client.AddGenericPacketHandler("avatarclassifiedsrequest", ClassifiedsRequest);
260 client.OnClassifiedInfoUpdate += ClassifiedInfoUpdate;
261 client.OnClassifiedInfoRequest += ClassifiedInfoRequest;
262 client.OnClassifiedDelete += ClassifiedDelete;
263
264 // Picks
265 client.AddGenericPacketHandler("avatarpicksrequest", PicksRequest);
266 client.AddGenericPacketHandler("pickinforequest", PickInfoRequest);
267 client.OnPickInfoUpdate += PickInfoUpdate;
268 client.OnPickDelete += PickDelete;
269
270 // Notes
271 client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest);
272 client.OnAvatarNotesUpdate += NotesUpdate;
273 }
274 #endregion Region Event Handlers
275
276 #region Classified
277 ///
278 /// <summary>
279 /// Handles the avatar classifieds request.
280 /// </summary>
281 /// <param name='sender'>
282 /// Sender.
283 /// </param>
284 /// <param name='method'>
285 /// Method.
286 /// </param>
287 /// <param name='args'>
288 /// Arguments.
289 /// </param>
290 public void ClassifiedsRequest(Object sender, string method, List<String> args)
291 {
292 if (!(sender is IClientAPI))
293 return;
294
295 IClientAPI remoteClient = (IClientAPI)sender;
296
297 UUID targetID;
298 UUID.TryParse(args[0], out targetID);
299
300 // Can't handle NPC yet...
301 ScenePresence p = FindPresence(targetID);
302
303 if (null != p)
304 {
305 if (p.PresenceType == PresenceType.Npc)
306 return;
307 }
308
309 string serverURI = string.Empty;
310 GetUserProfileServerURI(targetID, out serverURI);
311 UUID creatorId = UUID.Zero;
312 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
313
314 OSDMap parameters= new OSDMap();
315 UUID.TryParse(args[0], out creatorId);
316 parameters.Add("creatorId", OSD.FromUUID(creatorId));
317 OSD Params = (OSD)parameters;
318 if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
319 {
320 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
321 return;
322 }
323
324 parameters = (OSDMap)Params;
325
326 OSDArray list = (OSDArray)parameters["result"];
327
328
329 foreach(OSD map in list)
330 {
331 OSDMap m = (OSDMap)map;
332 UUID cid = m["classifieduuid"].AsUUID();
333 string name = m["name"].AsString();
334
335 classifieds[cid] = name;
336
337 lock (m_classifiedCache)
338 {
339 if (!m_classifiedCache.ContainsKey(cid))
340 {
341 m_classifiedCache.Add(cid,creatorId);
342 m_classifiedInterest.Add(cid, 0);
343 }
344
345 m_classifiedInterest[cid]++;
346 }
347 }
348
349 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
350 }
351
352 public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient)
353 {
354 UUID target = remoteClient.AgentId;
355 UserClassifiedAdd ad = new UserClassifiedAdd();
356 ad.ClassifiedId = queryClassifiedID;
357
358 lock (m_classifiedCache)
359 {
360 if (m_classifiedCache.ContainsKey(queryClassifiedID))
361 {
362 target = m_classifiedCache[queryClassifiedID];
363
364 m_classifiedInterest[queryClassifiedID] --;
365
366 if (m_classifiedInterest[queryClassifiedID] == 0)
367 {
368 m_classifiedInterest.Remove(queryClassifiedID);
369 m_classifiedCache.Remove(queryClassifiedID);
370 }
371 }
372 }
373
374 string serverURI = string.Empty;
375 GetUserProfileServerURI(target, out serverURI);
376
377 object Ad = (object)ad;
378 if(!JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString()))
379 {
380 remoteClient.SendAgentAlertMessage(
381 "Error getting classified info", false);
382 return;
383 }
384 ad = (UserClassifiedAdd) Ad;
385
386 if(ad.CreatorId == UUID.Zero)
387 return;
388
389 Vector3 globalPos = new Vector3();
390 Vector3.TryParse(ad.GlobalPos, out globalPos);
391
392 remoteClient.SendClassifiedInfoReply(ad.ClassifiedId, ad.CreatorId, (uint)ad.CreationDate, (uint)ad.ExpirationDate,
393 (uint)ad.Category, ad.Name, ad.Description, ad.ParcelId, (uint)ad.ParentEstate,
394 ad.SnapshotId, ad.SimName, globalPos, ad.ParcelName, ad.Flags, ad.Price);
395
396 }
397
398 /// <summary>
399 /// Classifieds info update.
400 /// </summary>
401 /// <param name='queryclassifiedID'>
402 /// Queryclassified I.
403 /// </param>
404 /// <param name='queryCategory'>
405 /// Query category.
406 /// </param>
407 /// <param name='queryName'>
408 /// Query name.
409 /// </param>
410 /// <param name='queryDescription'>
411 /// Query description.
412 /// </param>
413 /// <param name='queryParcelID'>
414 /// Query parcel I.
415 /// </param>
416 /// <param name='queryParentEstate'>
417 /// Query parent estate.
418 /// </param>
419 /// <param name='querySnapshotID'>
420 /// Query snapshot I.
421 /// </param>
422 /// <param name='queryGlobalPos'>
423 /// Query global position.
424 /// </param>
425 /// <param name='queryclassifiedFlags'>
426 /// Queryclassified flags.
427 /// </param>
428 /// <param name='queryclassifiedPrice'>
429 /// Queryclassified price.
430 /// </param>
431 /// <param name='remoteClient'>
432 /// Remote client.
433 /// </param>
434 public void ClassifiedInfoUpdate(UUID queryclassifiedID, uint queryCategory, string queryName, string queryDescription, UUID queryParcelID,
435 uint queryParentEstate, UUID querySnapshotID, Vector3 queryGlobalPos, byte queryclassifiedFlags,
436 int queryclassifiedPrice, IClientAPI remoteClient)
437 {
438 UserClassifiedAdd ad = new UserClassifiedAdd();
439
440 Scene s = (Scene) remoteClient.Scene;
441 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
442 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
443 ScenePresence p = FindPresence(remoteClient.AgentId);
444
445 string serverURI = string.Empty;
446 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
447
448 if (land == null)
449 {
450 ad.ParcelName = string.Empty;
451 }
452 else
453 {
454 ad.ParcelName = land.LandData.Name;
455 }
456
457 ad.CreatorId = remoteClient.AgentId;
458 ad.ClassifiedId = queryclassifiedID;
459 ad.Category = Convert.ToInt32(queryCategory);
460 ad.Name = queryName;
461 ad.Description = queryDescription;
462 ad.ParentEstate = Convert.ToInt32(queryParentEstate);
463 ad.SnapshotId = querySnapshotID;
464 ad.SimName = remoteClient.Scene.RegionInfo.RegionName;
465 ad.GlobalPos = queryGlobalPos.ToString ();
466 ad.Flags = queryclassifiedFlags;
467 ad.Price = queryclassifiedPrice;
468 ad.ParcelId = p.currentParcelUUID;
469
470 object Ad = ad;
471
472 OSD.SerializeMembers(Ad);
473
474 if(!JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString()))
475 {
476 remoteClient.SendAgentAlertMessage(
477 "Error updating classified", false);
478 }
479 }
480
481 /// <summary>
482 /// Classifieds delete.
483 /// </summary>
484 /// <param name='queryClassifiedID'>
485 /// Query classified I.
486 /// </param>
487 /// <param name='remoteClient'>
488 /// Remote client.
489 /// </param>
490 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient)
491 {
492 string serverURI = string.Empty;
493 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
494
495 UUID classifiedId;
496 OSDMap parameters= new OSDMap();
497 UUID.TryParse(queryClassifiedID.ToString(), out classifiedId);
498 parameters.Add("classifiedId", OSD.FromUUID(classifiedId));
499 OSD Params = (OSD)parameters;
500 if(!JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString()))
501 {
502 remoteClient.SendAgentAlertMessage(
503 "Error classified delete", false);
504 }
505
506 parameters = (OSDMap)Params;
507 }
508 #endregion Classified
509
510 #region Picks
511 /// <summary>
512 /// Handles the avatar picks request.
513 /// </summary>
514 /// <param name='sender'>
515 /// Sender.
516 /// </param>
517 /// <param name='method'>
518 /// Method.
519 /// </param>
520 /// <param name='args'>
521 /// Arguments.
522 /// </param>
523 public void PicksRequest(Object sender, string method, List<String> args)
524 {
525 if (!(sender is IClientAPI))
526 return;
527
528 IClientAPI remoteClient = (IClientAPI)sender;
529
530 UUID targetId;
531 UUID.TryParse(args[0], out targetId);
532
533 // Can't handle NPC yet...
534 ScenePresence p = FindPresence(targetId);
535
536 if (null != p)
537 {
538 if (p.PresenceType == PresenceType.Npc)
539 return;
540 }
541
542 string serverURI = string.Empty;
543 GetUserProfileServerURI(targetId, out serverURI);
544
545 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
546
547 OSDMap parameters= new OSDMap();
548 parameters.Add("creatorId", OSD.FromUUID(targetId));
549 OSD Params = (OSD)parameters;
550 if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
551 {
552 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
553 return;
554 }
555
556 parameters = (OSDMap)Params;
557
558 OSDArray list = (OSDArray)parameters["result"];
559
560 foreach(OSD map in list)
561 {
562 OSDMap m = (OSDMap)map;
563 UUID cid = m["pickuuid"].AsUUID();
564 string name = m["name"].AsString();
565
566 m_log.DebugFormat("[PROFILES]: PicksRequest {0}", name);
567
568 picks[cid] = name;
569 }
570 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
571 }
572
573 /// <summary>
574 /// Handles the pick info request.
575 /// </summary>
576 /// <param name='sender'>
577 /// Sender.
578 /// </param>
579 /// <param name='method'>
580 /// Method.
581 /// </param>
582 /// <param name='args'>
583 /// Arguments.
584 /// </param>
585 public void PickInfoRequest(Object sender, string method, List<String> args)
586 {
587 if (!(sender is IClientAPI))
588 return;
589
590 UUID targetID;
591 UUID.TryParse(args[0], out targetID);
592 string serverURI = string.Empty;
593 GetUserProfileServerURI(targetID, out serverURI);
594 IClientAPI remoteClient = (IClientAPI)sender;
595
596 UserProfilePick pick = new UserProfilePick();
597 UUID.TryParse(args[0], out pick.CreatorId);
598 UUID.TryParse(args[1], out pick.PickId);
599
600
601 object Pick = (object)pick;
602 if(!JsonRpcRequest(ref Pick, "pickinforequest", serverURI, UUID.Random().ToString()))
603 {
604 remoteClient.SendAgentAlertMessage(
605 "Error selecting pick", false);
606 }
607 pick = (UserProfilePick) Pick;
608 if(pick.SnapshotId == UUID.Zero)
609 {
610 // In case of a new UserPick, the data may not be ready and we would send wrong data, skip it...
611 m_log.DebugFormat("[PROFILES]: PickInfoRequest: SnapshotID is {0}", UUID.Zero.ToString());
612 return;
613 }
614
615 Vector3 globalPos;
616 Vector3.TryParse(pick.GlobalPos,out globalPos);
617
618 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
619
620 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
621 pick.Desc,pick.SnapshotId,pick.User,pick.OriginalName,pick.SimName,
622 globalPos,pick.SortOrder,pick.Enabled);
623 }
624
625 /// <summary>
626 /// Updates the userpicks
627 /// </summary>
628 /// <param name='remoteClient'>
629 /// Remote client.
630 /// </param>
631 /// <param name='pickID'>
632 /// Pick I.
633 /// </param>
634 /// <param name='creatorID'>
635 /// the creator of the pick
636 /// </param>
637 /// <param name='topPick'>
638 /// Top pick.
639 /// </param>
640 /// <param name='name'>
641 /// Name.
642 /// </param>
643 /// <param name='desc'>
644 /// Desc.
645 /// </param>
646 /// <param name='snapshotID'>
647 /// Snapshot I.
648 /// </param>
649 /// <param name='sortOrder'>
650 /// Sort order.
651 /// </param>
652 /// <param name='enabled'>
653 /// Enabled.
654 /// </param>
655 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled)
656 {
657
658 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
659 UserProfilePick pick = new UserProfilePick();
660 string serverURI = string.Empty;
661 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
662 ScenePresence p = FindPresence(remoteClient.AgentId);
663
664 Vector3 avaPos = p.AbsolutePosition;
665 // Getting the global position for the Avatar
666 Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
667 remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
668 avaPos.Z);
669
670 string landOwnerName = string.Empty;
671 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y);
672 if(land.LandData.IsGroupOwned)
673 {
674 IGroupsModule groupMod = p.Scene.RequestModuleInterface<IGroupsModule>();
675 UUID groupId = land.LandData.GroupID;
676 GroupRecord groupRecord = groupMod.GetGroupRecord(groupId);
677 landOwnerName = groupRecord.GroupName;
678 }
679 else
680 {
681 IUserAccountService accounts = p.Scene.RequestModuleInterface<IUserAccountService>();
682 UserAccount user = accounts.GetUserAccount(p.Scene.RegionInfo.ScopeID, land.LandData.OwnerID);
683 landOwnerName = user.Name;
684 }
685
686 pick.PickId = pickID;
687 pick.CreatorId = creatorID;
688 pick.TopPick = topPick;
689 pick.Name = name;
690 pick.Desc = desc;
691 pick.ParcelId = p.currentParcelUUID;
692 pick.SnapshotId = snapshotID;
693 pick.User = landOwnerName;
694 pick.SimName = remoteClient.Scene.RegionInfo.RegionName;
695 pick.GlobalPos = posGlobal.ToString();
696 pick.SortOrder = sortOrder;
697 pick.Enabled = enabled;
698
699 object Pick = (object)pick;
700 if(!JsonRpcRequest(ref Pick, "picks_update", serverURI, UUID.Random().ToString()))
701 {
702 remoteClient.SendAgentAlertMessage(
703 "Error updating pick", false);
704 }
705
706 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString());
707 }
708
709 /// <summary>
710 /// Delete a Pick
711 /// </summary>
712 /// <param name='remoteClient'>
713 /// Remote client.
714 /// </param>
715 /// <param name='queryPickID'>
716 /// Query pick I.
717 /// </param>
718 public void PickDelete(IClientAPI remoteClient, UUID queryPickID)
719 {
720 string serverURI = string.Empty;
721 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
722
723 OSDMap parameters= new OSDMap();
724 parameters.Add("pickId", OSD.FromUUID(queryPickID));
725 OSD Params = (OSD)parameters;
726 if(!JsonRpcRequest(ref Params, "picks_delete", serverURI, UUID.Random().ToString()))
727 {
728 remoteClient.SendAgentAlertMessage(
729 "Error picks delete", false);
730 }
731 }
732 #endregion Picks
733
734 #region Notes
735 /// <summary>
736 /// Handles the avatar notes request.
737 /// </summary>
738 /// <param name='sender'>
739 /// Sender.
740 /// </param>
741 /// <param name='method'>
742 /// Method.
743 /// </param>
744 /// <param name='args'>
745 /// Arguments.
746 /// </param>
747 public void NotesRequest(Object sender, string method, List<String> args)
748 {
749 UserProfileNotes note = new UserProfileNotes();
750
751 if (!(sender is IClientAPI))
752 return;
753
754 IClientAPI remoteClient = (IClientAPI)sender;
755 string serverURI = string.Empty;
756 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
757 note.UserId = remoteClient.AgentId;
758 UUID.TryParse(args[0], out note.TargetId);
759
760 object Note = (object)note;
761 if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
762 {
763 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
764 return;
765 }
766 note = (UserProfileNotes) Note;
767
768 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
769 }
770
771 /// <summary>
772 /// Avatars the notes update.
773 /// </summary>
774 /// <param name='remoteClient'>
775 /// Remote client.
776 /// </param>
777 /// <param name='queryTargetID'>
778 /// Query target I.
779 /// </param>
780 /// <param name='queryNotes'>
781 /// Query notes.
782 /// </param>
783 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes)
784 {
785 UserProfileNotes note = new UserProfileNotes();
786
787 note.UserId = remoteClient.AgentId;
788 note.TargetId = queryTargetID;
789 note.Notes = queryNotes;
790
791 string serverURI = string.Empty;
792 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
793
794 object Note = note;
795 if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
796 {
797 return;
798 }
799 }
800 #endregion Notes
801
802 #region Avatar Properties
803 /// <summary>
804 /// Update the avatars interests .
805 /// </summary>
806 /// <param name='remoteClient'>
807 /// Remote client.
808 /// </param>
809 /// <param name='wantmask'>
810 /// Wantmask.
811 /// </param>
812 /// <param name='wanttext'>
813 /// Wanttext.
814 /// </param>
815 /// <param name='skillsmask'>
816 /// Skillsmask.
817 /// </param>
818 /// <param name='skillstext'>
819 /// Skillstext.
820 /// </param>
821 /// <param name='languages'>
822 /// Languages.
823 /// </param>
824 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages)
825 {
826 UserProfileProperties prop = new UserProfileProperties();
827
828 prop.UserId = remoteClient.AgentId;
829 prop.WantToMask = (int)wantmask;
830 prop.WantToText = wanttext;
831 prop.SkillsMask = (int)skillsmask;
832 prop.SkillsText = skillstext;
833 prop.Language = languages;
834
835 string serverURI = string.Empty;
836 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
837
838 object Param = prop;
839 if(!JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString()))
840 {
841 remoteClient.SendAgentAlertMessage(
842 "Error updating interests", false);
843 }
844 }
845
846 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
847 {
848 if ( String.IsNullOrEmpty(avatarID.ToString()) || String.IsNullOrEmpty(remoteClient.AgentId.ToString()))
849 {
850 // Looking for a reason that some viewers are sending null Id's
851 m_log.DebugFormat("[PROFILES]: This should not happen remoteClient.AgentId {0} - avatarID {1}", remoteClient.AgentId, avatarID);
852 return;
853 }
854
855 // Can't handle NPC yet...
856 ScenePresence p = FindPresence(avatarID);
857
858 if (null != p)
859 {
860 if (p.PresenceType == PresenceType.Npc)
861 return;
862 }
863
864 string serverURI = string.Empty;
865 bool foreign = GetUserProfileServerURI(avatarID, out serverURI);
866
867 UserAccount account = null;
868 Dictionary<string,object> userInfo;
869
870 if (!foreign)
871 {
872 account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
873 }
874 else
875 {
876 userInfo = new Dictionary<string, object>();
877 }
878
879 Byte[] charterMember = new Byte[1];
880 string born = String.Empty;
881 uint flags = 0x00;
882
883 if (null != account)
884 {
885 if (account.UserTitle == "")
886 {
887 charterMember[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
888 }
889 else
890 {
891 charterMember = Utils.StringToBytes(account.UserTitle);
892 }
893
894 born = Util.ToDateTime(account.Created).ToString(
895 "M/d/yyyy", CultureInfo.InvariantCulture);
896 flags = (uint)(account.UserFlags & 0xff);
897 }
898 else
899 {
900 if (GetUserAccountData(avatarID, out userInfo) == true)
901 {
902 if ((string)userInfo["user_title"] == "")
903 {
904 charterMember[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
905 }
906 else
907 {
908 charterMember = Utils.StringToBytes((string)userInfo["user_title"]);
909 }
910
911 int val_born = (int)userInfo["user_created"];
912 born = Util.ToDateTime(val_born).ToString(
913 "M/d/yyyy", CultureInfo.InvariantCulture);
914
915 // picky, picky
916 int val_flags = (int)userInfo["user_flags"];
917 flags = (uint)(val_flags & 0xff);
918 }
919 }
920
921 UserProfileProperties props = new UserProfileProperties();
922 string result = string.Empty;
923
924 props.UserId = avatarID;
925 GetProfileData(ref props, out result);
926
927 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags,
928 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
929
930
931 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask,
932 props.SkillsText, props.Language);
933 }
934
935 /// <summary>
936 /// Updates the avatar properties.
937 /// </summary>
938 /// <param name='remoteClient'>
939 /// Remote client.
940 /// </param>
941 /// <param name='newProfile'>
942 /// New profile.
943 /// </param>
944 public void AvatarPropertiesUpdate(IClientAPI remoteClient, UserProfileData newProfile)
945 {
946 if (remoteClient.AgentId == newProfile.ID)
947 {
948 UserProfileProperties prop = new UserProfileProperties();
949
950 prop.UserId = remoteClient.AgentId;
951 prop.WebUrl = newProfile.ProfileUrl;
952 prop.ImageId = newProfile.Image;
953 prop.AboutText = newProfile.AboutText;
954 prop.FirstLifeImageId = newProfile.FirstLifeImage;
955 prop.FirstLifeText = newProfile.FirstLifeAboutText;
956
957 string serverURI = string.Empty;
958 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
959
960 object Prop = prop;
961
962 if(!JsonRpcRequest(ref Prop, "avatar_properties_update", serverURI, UUID.Random().ToString()))
963 {
964 remoteClient.SendAgentAlertMessage(
965 "Error updating properties", false);
966 }
967
968 RequestAvatarProperties(remoteClient, newProfile.ID);
969 }
970 }
971
972 /// <summary>
973 /// Gets the profile data.
974 /// </summary>
975 /// <returns>
976 /// The profile data.
977 /// </returns>
978 /// <param name='userID'>
979 /// User I.
980 /// </param>
981 bool GetProfileData(ref UserProfileProperties properties, out string message)
982 {
983 // Can't handle NPC yet...
984 ScenePresence p = FindPresence(properties.UserId);
985
986 if (null != p)
987 {
988 if (p.PresenceType == PresenceType.Npc)
989 {
990 message = "Id points to NPC";
991 return false;
992 }
993 }
994
995 string serverURI = string.Empty;
996 GetUserProfileServerURI(properties.UserId, out serverURI);
997
998 // This is checking a friend on the home grid
999 // Not HG friend
1000 if ( String.IsNullOrEmpty(serverURI))
1001 {
1002 message = "No Presence - foreign friend";
1003 return false;
1004 }
1005
1006 object Prop = (object)properties;
1007 JsonRpcRequest(ref Prop, "avatar_properties_request", serverURI, UUID.Random().ToString());
1008 properties = (UserProfileProperties)Prop;
1009
1010 message = "Success";
1011 return true;
1012 }
1013 #endregion Avatar Properties
1014
1015 #region Utils
1016 bool GetImageAssets(UUID avatarId)
1017 {
1018 string profileServerURI = string.Empty;
1019 string assetServerURI = string.Empty;
1020
1021 bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI);
1022
1023 if(!foreign)
1024 return true;
1025
1026 assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI");
1027
1028 OSDMap parameters= new OSDMap();
1029 parameters.Add("avatarId", OSD.FromUUID(avatarId));
1030 OSD Params = (OSD)parameters;
1031 if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
1032 {
1033 return false;
1034 }
1035
1036 parameters = (OSDMap)Params;
1037
1038 OSDArray list = (OSDArray)parameters["result"];
1039
1040 foreach(OSD asset in list)
1041 {
1042 OSDString assetId = (OSDString)asset;
1043
1044 Scene.AssetService.Get(string.Format("{0}/{1}",assetServerURI, assetId.AsString()));
1045 }
1046 return true;
1047 }
1048
1049 /// <summary>
1050 /// Gets the user account data.
1051 /// </summary>
1052 /// <returns>
1053 /// The user profile data.
1054 /// </returns>
1055 /// <param name='userID'>
1056 /// If set to <c>true</c> user I.
1057 /// </param>
1058 /// <param name='userInfo'>
1059 /// If set to <c>true</c> user info.
1060 /// </param>
1061 bool GetUserAccountData(UUID userID, out Dictionary<string, object> userInfo)
1062 {
1063 Dictionary<string,object> info = new Dictionary<string, object>();
1064
1065 if (UserManagementModule.IsLocalGridUser(userID))
1066 {
1067 // Is local
1068 IUserAccountService uas = Scene.UserAccountService;
1069 UserAccount account = uas.GetUserAccount(Scene.RegionInfo.ScopeID, userID);
1070
1071 info["user_flags"] = account.UserFlags;
1072 info["user_created"] = account.Created;
1073
1074 if (!String.IsNullOrEmpty(account.UserTitle))
1075 info["user_title"] = account.UserTitle;
1076 else
1077 info["user_title"] = "";
1078
1079 userInfo = info;
1080
1081 return false;
1082 }
1083 else
1084 {
1085 // Is Foreign
1086 string home_url = UserManagementModule.GetUserServerURL(userID, "HomeURI");
1087
1088 if (String.IsNullOrEmpty(home_url))
1089 {
1090 info["user_flags"] = 0;
1091 info["user_created"] = 0;
1092 info["user_title"] = "Unavailable";
1093
1094 userInfo = info;
1095 return true;
1096 }
1097
1098 UserAgentServiceConnector uConn = new UserAgentServiceConnector(home_url);
1099
1100 Dictionary<string, object> account = uConn.GetUserInfo(userID);
1101
1102 if (account.Count > 0)
1103 {
1104 if (account.ContainsKey("user_flags"))
1105 info["user_flags"] = account["user_flags"];
1106 else
1107 info["user_flags"] = "";
1108
1109 if (account.ContainsKey("user_created"))
1110 info["user_created"] = account["user_created"];
1111 else
1112 info["user_created"] = "";
1113
1114 info["user_title"] = "HG Visitor";
1115 }
1116 else
1117 {
1118 info["user_flags"] = 0;
1119 info["user_created"] = 0;
1120 info["user_title"] = "HG Visitor";
1121 }
1122 userInfo = info;
1123 return true;
1124 }
1125 }
1126
1127 /// <summary>
1128 /// Gets the user profile server UR.
1129 /// </summary>
1130 /// <returns>
1131 /// The user profile server UR.
1132 /// </returns>
1133 /// <param name='userID'>
1134 /// If set to <c>true</c> user I.
1135 /// </param>
1136 /// <param name='serverURI'>
1137 /// If set to <c>true</c> server UR.
1138 /// </param>
1139 bool GetUserProfileServerURI(UUID userID, out string serverURI)
1140 {
1141 bool local;
1142 local = UserManagementModule.IsLocalGridUser(userID);
1143
1144 if (!local)
1145 {
1146 serverURI = UserManagementModule.GetUserServerURL(userID, "ProfileServerURI");
1147 // Is Foreign
1148 return true;
1149 }
1150 else
1151 {
1152 serverURI = ProfileServerUri;
1153 // Is local
1154 return false;
1155 }
1156 }
1157
1158 /// <summary>
1159 /// Finds the presence.
1160 /// </summary>
1161 /// <returns>
1162 /// The presence.
1163 /// </returns>
1164 /// <param name='clientID'>
1165 /// Client I.
1166 /// </param>
1167 ScenePresence FindPresence(UUID clientID)
1168 {
1169 ScenePresence p;
1170
1171 p = Scene.GetScenePresence(clientID);
1172 if (p != null && !p.IsChildAgent)
1173 return p;
1174
1175 return null;
1176 }
1177 #endregion Util
1178
1179 #region Web Util
1180 /// <summary>
1181 /// Sends json-rpc request with a serializable type.
1182 /// </summary>
1183 /// <returns>
1184 /// OSD Map.
1185 /// </returns>
1186 /// <param name='parameters'>
1187 /// Serializable type .
1188 /// </param>
1189 /// <param name='method'>
1190 /// Json-rpc method to call.
1191 /// </param>
1192 /// <param name='uri'>
1193 /// URI of json-rpc service.
1194 /// </param>
1195 /// <param name='jsonId'>
1196 /// Id for our call.
1197 /// </param>
1198 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1199 {
1200 if (jsonId == null)
1201 throw new ArgumentNullException ("jsonId");
1202 if (uri == null)
1203 throw new ArgumentNullException ("uri");
1204 if (method == null)
1205 throw new ArgumentNullException ("method");
1206 if (parameters == null)
1207 throw new ArgumentNullException ("parameters");
1208
1209 // Prep our payload
1210 OSDMap json = new OSDMap();
1211
1212 json.Add("jsonrpc", OSD.FromString("2.0"));
1213 json.Add("id", OSD.FromString(jsonId));
1214 json.Add("method", OSD.FromString(method));
1215
1216 json.Add("params", OSD.SerializeMembers(parameters));
1217
1218 string jsonRequestData = OSDParser.SerializeJsonString(json);
1219 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1220
1221 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1222
1223 webRequest.ContentType = "application/json-rpc";
1224 webRequest.Method = "POST";
1225
1226 Stream dataStream = webRequest.GetRequestStream();
1227 dataStream.Write(content, 0, content.Length);
1228 dataStream.Close();
1229
1230 WebResponse webResponse = null;
1231 try
1232 {
1233 webResponse = webRequest.GetResponse();
1234 }
1235 catch (WebException e)
1236 {
1237 Console.WriteLine("Web Error" + e.Message);
1238 Console.WriteLine ("Please check input");
1239 return false;
1240 }
1241
1242 Stream rstream = webResponse.GetResponseStream();
1243
1244 OSDMap mret = new OSDMap();
1245 try
1246 {
1247 mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1248 }
1249 catch (Exception e)
1250 {
1251 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1252 return false;
1253 }
1254
1255
1256 if (mret.ContainsKey("error"))
1257 return false;
1258
1259 // get params...
1260 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1261 return true;
1262 }
1263
1264 /// <summary>
1265 /// Sends json-rpc request with OSD parameter.
1266 /// </summary>
1267 /// <returns>
1268 /// The rpc request.
1269 /// </returns>
1270 /// <param name='data'>
1271 /// data - incoming as parameters, outgong as result/error
1272 /// </param>
1273 /// <param name='method'>
1274 /// Json-rpc method to call.
1275 /// </param>
1276 /// <param name='uri'>
1277 /// URI of json-rpc service.
1278 /// </param>
1279 /// <param name='jsonId'>
1280 /// If set to <c>true</c> json identifier.
1281 /// </param>
1282 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1283 {
1284 OSDMap map = new OSDMap();
1285
1286 map["jsonrpc"] = "2.0";
1287 if(string.IsNullOrEmpty(jsonId))
1288 map["id"] = UUID.Random().ToString();
1289 else
1290 map["id"] = jsonId;
1291
1292 map["method"] = method;
1293 map["params"] = data;
1294
1295 string jsonRequestData = OSDParser.SerializeJsonString(map);
1296 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1297
1298 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1299 webRequest.ContentType = "application/json-rpc";
1300 webRequest.Method = "POST";
1301
1302 Stream dataStream = webRequest.GetRequestStream();
1303 dataStream.Write(content, 0, content.Length);
1304 dataStream.Close();
1305
1306 WebResponse webResponse = null;
1307 try
1308 {
1309 webResponse = webRequest.GetResponse();
1310 }
1311 catch (WebException e)
1312 {
1313 Console.WriteLine("Web Error" + e.Message);
1314 Console.WriteLine ("Please check input");
1315 return false;
1316 }
1317
1318 Stream rstream = webResponse.GetResponseStream();
1319
1320 OSDMap response = new OSDMap();
1321 try
1322 {
1323 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1324 }
1325 catch (Exception e)
1326 {
1327 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1328 return false;
1329 }
1330
1331 if(response.ContainsKey("error"))
1332 {
1333 data = response["error"];
1334 return false;
1335 }
1336
1337 data = response;
1338
1339 return true;
1340 }
1341 #endregion Web Util
1342 }
1343} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index fff86d5..de8925d 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq;
31using System.Reflection; 32using System.Reflection;
32using System.Text; 33using System.Text;
33using log4net; 34using log4net;
@@ -37,6 +38,7 @@ using OpenMetaverse;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
39using OpenSim.Framework.Servers; 40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
42using Caps=OpenSim.Framework.Capabilities.Caps; 44using Caps=OpenSim.Framework.Capabilities.Caps;
@@ -57,8 +59,9 @@ namespace OpenSim.Region.CoreModules.Framework
57 /// </summary> 59 /// </summary>
58 protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>(); 60 protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>();
59 61
60 protected Dictionary<UUID, string> capsPaths = new Dictionary<UUID, string>(); 62 protected Dictionary<UUID, string> m_capsPaths = new Dictionary<UUID, string>();
61 protected Dictionary<UUID, Dictionary<ulong, string>> childrenSeeds 63
64 protected Dictionary<UUID, Dictionary<ulong, string>> m_childrenSeeds
62 = new Dictionary<UUID, Dictionary<ulong, string>>(); 65 = new Dictionary<UUID, Dictionary<ulong, string>>();
63 66
64 public void Initialise(IConfigSource source) 67 public void Initialise(IConfigSource source)
@@ -70,9 +73,24 @@ namespace OpenSim.Region.CoreModules.Framework
70 m_scene = scene; 73 m_scene = scene;
71 m_scene.RegisterModuleInterface<ICapabilitiesModule>(this); 74 m_scene.RegisterModuleInterface<ICapabilitiesModule>(this);
72 75
73 MainConsole.Instance.Commands.AddCommand("Comms", false, "show caps", 76 MainConsole.Instance.Commands.AddCommand(
74 "show caps", 77 "Comms", false, "show caps list",
75 "Shows all registered capabilities for users", HandleShowCapsCommand); 78 "show caps list",
79 "Shows list of registered capabilities for users.", HandleShowCapsListCommand);
80
81 MainConsole.Instance.Commands.AddCommand(
82 "Comms", false, "show caps stats by user",
83 "show caps stats by user [<first-name> <last-name>]",
84 "Shows statistics on capabilities use by user.",
85 "If a user name is given, then prints a detailed breakdown of caps use ordered by number of requests received.",
86 HandleShowCapsStatsByUserCommand);
87
88 MainConsole.Instance.Commands.AddCommand(
89 "Comms", false, "show caps stats by cap",
90 "show caps stats by cap [<cap-name>]",
91 "Shows statistics on capabilities use by capability.",
92 "If a capability name is given, then prints a detailed breakdown of use by each user.",
93 HandleShowCapsStatsByCapCommand);
76 } 94 }
77 95
78 public void RegionLoaded(Scene scene) 96 public void RegionLoaded(Scene scene)
@@ -106,35 +124,38 @@ namespace OpenSim.Region.CoreModules.Framework
106 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags)) 124 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags))
107 return; 125 return;
108 126
127 Caps caps;
109 String capsObjectPath = GetCapsPath(agentId); 128 String capsObjectPath = GetCapsPath(agentId);
110 129
111 if (m_capsObjects.ContainsKey(circuitCode)) 130 lock (m_capsObjects)
112 { 131 {
113 Caps oldCaps = m_capsObjects[circuitCode]; 132 if (m_capsObjects.ContainsKey(circuitCode))
114 133 {
115 m_log.DebugFormat( 134 Caps oldCaps = m_capsObjects[circuitCode];
116 "[CAPS]: Recreating caps for agent {0}. Old caps path {1}, new caps path {2}. ", 135
117 agentId, oldCaps.CapsObjectPath, capsObjectPath); 136 //m_log.WarnFormat(
118 // This should not happen. The caller code is confused. We need to fix that. 137 // "[CAPS]: Recreating caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ",
119 // CAPs can never be reregistered, or the client will be confused. 138 // agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath);
120 // Hence this return here. 139 }
121 //return;
122 }
123
124 Caps caps = new Caps(MainServer.Instance, m_scene.RegionInfo.ExternalHostName,
125 (MainServer.Instance == null) ? 0: MainServer.Instance.Port,
126 capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
127 140
128 m_capsObjects[circuitCode] = caps; 141 caps = new Caps(MainServer.Instance, m_scene.RegionInfo.ExternalHostName,
142 (MainServer.Instance == null) ? 0: MainServer.Instance.Port,
143 capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
129 144
145 m_capsObjects[circuitCode] = caps;
146 }
130 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); 147 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps);
131 } 148 }
132 149
133 public void RemoveCaps(UUID agentId, uint circuitCode) 150 public void RemoveCaps(UUID agentId, uint circuitCode)
134 { 151 {
135 if (childrenSeeds.ContainsKey(agentId)) 152 m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName);
153 lock (m_childrenSeeds)
136 { 154 {
137 childrenSeeds.Remove(agentId); 155 if (m_childrenSeeds.ContainsKey(agentId))
156 {
157 m_childrenSeeds.Remove(agentId);
158 }
138 } 159 }
139 160
140 lock (m_capsObjects) 161 lock (m_capsObjects)
@@ -180,16 +201,22 @@ namespace OpenSim.Region.CoreModules.Framework
180 201
181 public void SetAgentCapsSeeds(AgentCircuitData agent) 202 public void SetAgentCapsSeeds(AgentCircuitData agent)
182 { 203 {
183 capsPaths[agent.AgentID] = agent.CapsPath; 204 lock (m_capsPaths)
184 childrenSeeds[agent.AgentID] 205 m_capsPaths[agent.AgentID] = agent.CapsPath;
185 = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds); 206
207 lock (m_childrenSeeds)
208 m_childrenSeeds[agent.AgentID]
209 = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds);
186 } 210 }
187 211
188 public string GetCapsPath(UUID agentId) 212 public string GetCapsPath(UUID agentId)
189 { 213 {
190 if (capsPaths.ContainsKey(agentId)) 214 lock (m_capsPaths)
191 { 215 {
192 return capsPaths[agentId]; 216 if (m_capsPaths.ContainsKey(agentId))
217 {
218 return m_capsPaths[agentId];
219 }
193 } 220 }
194 221
195 return null; 222 return null;
@@ -198,17 +225,24 @@ namespace OpenSim.Region.CoreModules.Framework
198 public Dictionary<ulong, string> GetChildrenSeeds(UUID agentID) 225 public Dictionary<ulong, string> GetChildrenSeeds(UUID agentID)
199 { 226 {
200 Dictionary<ulong, string> seeds = null; 227 Dictionary<ulong, string> seeds = null;
201 if (childrenSeeds.TryGetValue(agentID, out seeds)) 228
202 return seeds; 229 lock (m_childrenSeeds)
230 if (m_childrenSeeds.TryGetValue(agentID, out seeds))
231 return seeds;
232
203 return new Dictionary<ulong, string>(); 233 return new Dictionary<ulong, string>();
204 } 234 }
205 235
206 public void DropChildSeed(UUID agentID, ulong handle) 236 public void DropChildSeed(UUID agentID, ulong handle)
207 { 237 {
208 Dictionary<ulong, string> seeds; 238 Dictionary<ulong, string> seeds;
209 if (childrenSeeds.TryGetValue(agentID, out seeds)) 239
240 lock (m_childrenSeeds)
210 { 241 {
211 seeds.Remove(handle); 242 if (m_childrenSeeds.TryGetValue(agentID, out seeds))
243 {
244 seeds.Remove(handle);
245 }
212 } 246 }
213 } 247 }
214 248
@@ -216,53 +250,339 @@ namespace OpenSim.Region.CoreModules.Framework
216 { 250 {
217 Dictionary<ulong, string> seeds; 251 Dictionary<ulong, string> seeds;
218 string returnval; 252 string returnval;
219 if (childrenSeeds.TryGetValue(agentID, out seeds)) 253
254 lock (m_childrenSeeds)
220 { 255 {
221 if (seeds.TryGetValue(handle, out returnval)) 256 if (m_childrenSeeds.TryGetValue(agentID, out seeds))
222 return returnval; 257 {
258 if (seeds.TryGetValue(handle, out returnval))
259 return returnval;
260 }
223 } 261 }
262
224 return null; 263 return null;
225 } 264 }
226 265
227 public void SetChildrenSeed(UUID agentID, Dictionary<ulong, string> seeds) 266 public void SetChildrenSeed(UUID agentID, Dictionary<ulong, string> seeds)
228 { 267 {
229 //m_log.DebugFormat(" !!! Setting child seeds in {0} to {1}", m_scene.RegionInfo.RegionName, seeds.Count); 268 //m_log.DebugFormat(" !!! Setting child seeds in {0} to {1}", m_scene.RegionInfo.RegionName, seeds.Count);
230 childrenSeeds[agentID] = seeds; 269
270 lock (m_childrenSeeds)
271 m_childrenSeeds[agentID] = seeds;
231 } 272 }
232 273
233 public void DumpChildrenSeeds(UUID agentID) 274 public void DumpChildrenSeeds(UUID agentID)
234 { 275 {
235 m_log.Info("================ ChildrenSeed "+m_scene.RegionInfo.RegionName+" ================"); 276 m_log.Info("================ ChildrenSeed "+m_scene.RegionInfo.RegionName+" ================");
236 foreach (KeyValuePair<ulong, string> kvp in childrenSeeds[agentID]) 277
278 lock (m_childrenSeeds)
279 {
280 foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID])
281 {
282 uint x, y;
283 Utils.LongToUInts(kvp.Key, out x, out y);
284 x = x / Constants.RegionSize;
285 y = y / Constants.RegionSize;
286 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
287 }
288 }
289 }
290
291 private void HandleShowCapsListCommand(string module, string[] cmdParams)
292 {
293 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
294 return;
295
296 StringBuilder capsReport = new StringBuilder();
297 capsReport.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName);
298
299 lock (m_capsObjects)
237 { 300 {
238 uint x, y; 301 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
239 Utils.LongToUInts(kvp.Key, out x, out y); 302 {
240 x = x / Constants.RegionSize; 303 capsReport.AppendFormat("** Circuit {0}:\n", kvp.Key);
241 y = y / Constants.RegionSize; 304 Caps caps = kvp.Value;
242 m_log.Info(" >> "+x+", "+y+": "+kvp.Value); 305
306 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
307 {
308 Uri uri = new Uri(kvp2.Value.ToString());
309 capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
310 }
311
312 foreach (KeyValuePair<string, PollServiceEventArgs> kvp2 in caps.GetPollHandlers())
313 capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, kvp2.Value.Url);
314
315 foreach (KeyValuePair<string, string> kvp3 in caps.ExternalCapsHandlers)
316 capsReport.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value);
317 }
243 } 318 }
319
320 MainConsole.Instance.Output(capsReport.ToString());
244 } 321 }
245 322
246 private void HandleShowCapsCommand(string module, string[] cmdparams) 323 private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams)
247 { 324 {
248 StringBuilder caps = new StringBuilder(); 325 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
249 caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); 326 return;
327
328 if (cmdParams.Length != 5 && cmdParams.Length != 6)
329 {
330 MainConsole.Instance.Output("Usage: show caps stats by cap [<cap-name>]");
331 return;
332 }
333
334 StringBuilder sb = new StringBuilder();
335 sb.AppendFormat("Region {0}:\n", m_scene.Name);
336
337 if (cmdParams.Length == 5)
338 {
339 BuildSummaryStatsByCapReport(sb);
340 }
341 else if (cmdParams.Length == 6)
342 {
343 BuildDetailedStatsByCapReport(sb, cmdParams[5]);
344 }
345
346 MainConsole.Instance.Output(sb.ToString());
347 }
348
349 private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName)
350 {
351 /*
352 sb.AppendFormat("Capability name {0}\n", capName);
353
354 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
355 cdt.AddColumn("User Name", 34);
356 cdt.AddColumn("Req Received", 12);
357 cdt.AddColumn("Req Handled", 12);
358 cdt.Indent = 2;
359
360 Dictionary<string, int> receivedStats = new Dictionary<string, int>();
361 Dictionary<string, int> handledStats = new Dictionary<string, int>();
362
363 m_scene.ForEachScenePresence(
364 sp =>
365 {
366 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
250 367
251 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects) 368 if (caps == null)
369 return;
370
371 Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers();
372
373 IRequestHandler reqHandler;
374 if (capsHandlers.TryGetValue(capName, out reqHandler))
375 {
376 receivedStats[sp.Name] = reqHandler.RequestsReceived;
377 handledStats[sp.Name] = reqHandler.RequestsHandled;
378 }
379 else
380 {
381 PollServiceEventArgs pollHandler = null;
382 if (caps.TryGetPollHandler(capName, out pollHandler))
383 {
384 receivedStats[sp.Name] = pollHandler.RequestsReceived;
385 handledStats[sp.Name] = pollHandler.RequestsHandled;
386 }
387 }
388 }
389 );
390
391 foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value))
252 { 392 {
253 caps.AppendFormat("** Circuit {0}:\n", kvp.Key); 393 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]);
394 }
395
396 sb.Append(cdt.ToString());
397 */
398 }
399
400 private void BuildSummaryStatsByCapReport(StringBuilder sb)
401 {
402 /*
403 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
404 cdt.AddColumn("Name", 34);
405 cdt.AddColumn("Req Received", 12);
406 cdt.AddColumn("Req Handled", 12);
407 cdt.Indent = 2;
408
409 Dictionary<string, int> receivedStats = new Dictionary<string, int>();
410 Dictionary<string, int> handledStats = new Dictionary<string, int>();
254 411
255 for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) 412 m_scene.ForEachScenePresence(
413 sp =>
256 { 414 {
257 Uri uri = new Uri(kvp2.Value.ToString()); 415 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
258 caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery); 416
417 if (caps == null)
418 return;
419
420 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
421 {
422 string reqName = reqHandler.Name ?? "";
423
424 if (!receivedStats.ContainsKey(reqName))
425 {
426 receivedStats[reqName] = reqHandler.RequestsReceived;
427 handledStats[reqName] = reqHandler.RequestsHandled;
428 }
429 else
430 {
431 receivedStats[reqName] += reqHandler.RequestsReceived;
432 handledStats[reqName] += reqHandler.RequestsHandled;
433 }
434 }
435
436 foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
437 {
438 string name = kvp.Key;
439 PollServiceEventArgs pollHandler = kvp.Value;
440
441 if (!receivedStats.ContainsKey(name))
442 {
443 receivedStats[name] = pollHandler.RequestsReceived;
444 handledStats[name] = pollHandler.RequestsHandled;
445 }
446 else
447 {
448 receivedStats[name] += pollHandler.RequestsReceived;
449 handledStats[name] += pollHandler.RequestsHandled;
450 }
451 }
259 } 452 }
453 );
454
455 foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value))
456 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]);
457
458 sb.Append(cdt.ToString());
459 */
460 }
461
462 private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams)
463 {
464 /*
465 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
466 return;
467
468 if (cmdParams.Length != 5 && cmdParams.Length != 7)
469 {
470 MainConsole.Instance.Output("Usage: show caps stats by user [<first-name> <last-name>]");
471 return;
472 }
473
474 StringBuilder sb = new StringBuilder();
475 sb.AppendFormat("Region {0}:\n", m_scene.Name);
476
477 if (cmdParams.Length == 5)
478 {
479 BuildSummaryStatsByUserReport(sb);
480 }
481 else if (cmdParams.Length == 7)
482 {
483 string firstName = cmdParams[5];
484 string lastName = cmdParams[6];
485
486 ScenePresence sp = m_scene.GetScenePresence(firstName, lastName);
487
488 if (sp == null)
489 return;
260 490
261 foreach (KeyValuePair<string, string> kvp3 in kvp.Value.ExternalCapsHandlers) 491 BuildDetailedStatsByUserReport(sb, sp);
262 caps.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value);
263 } 492 }
264 493
265 MainConsole.Instance.Output(caps.ToString()); 494 MainConsole.Instance.Output(sb.ToString());
495 */
496 }
497
498 private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp)
499 {
500 /*
501 sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root");
502
503 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
504 cdt.AddColumn("Cap Name", 34);
505 cdt.AddColumn("Req Received", 12);
506 cdt.AddColumn("Req Handled", 12);
507 cdt.Indent = 2;
508
509 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
510
511 if (caps == null)
512 return;
513
514 List<CapTableRow> capRows = new List<CapTableRow>();
515
516 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
517 capRows.Add(new CapTableRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled));
518
519 foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
520 capRows.Add(new CapTableRow(kvp.Key, kvp.Value.RequestsReceived, kvp.Value.RequestsHandled));
521
522 foreach (CapTableRow ctr in capRows.OrderByDescending(ctr => ctr.RequestsReceived))
523 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled);
524
525 sb.Append(cdt.ToString());
526 */
527 }
528
529 private void BuildSummaryStatsByUserReport(StringBuilder sb)
530 {
531 /*
532 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
533 cdt.AddColumn("Name", 32);
534 cdt.AddColumn("Type", 5);
535 cdt.AddColumn("Req Received", 12);
536 cdt.AddColumn("Req Handled", 12);
537 cdt.Indent = 2;
538
539 m_scene.ForEachScenePresence(
540 sp =>
541 {
542 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
543
544 if (caps == null)
545 return;
546
547 Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers();
548
549 int totalRequestsReceived = 0;
550 int totalRequestsHandled = 0;
551
552 foreach (IRequestHandler reqHandler in capsHandlers.Values)
553 {
554 totalRequestsReceived += reqHandler.RequestsReceived;
555 totalRequestsHandled += reqHandler.RequestsHandled;
556 }
557
558 Dictionary<string, PollServiceEventArgs> capsPollHandlers = caps.GetPollHandlers();
559
560 foreach (PollServiceEventArgs handler in capsPollHandlers.Values)
561 {
562 totalRequestsReceived += handler.RequestsReceived;
563 totalRequestsHandled += handler.RequestsHandled;
564 }
565
566 cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled);
567 }
568 );
569
570 sb.Append(cdt.ToString());
571 */
572 }
573
574 private class CapTableRow
575 {
576 public string Name { get; set; }
577 public int RequestsReceived { get; set; }
578 public int RequestsHandled { get; set; }
579
580 public CapTableRow(string name, int requestsReceived, int requestsHandled)
581 {
582 Name = name;
583 RequestsReceived = requestsReceived;
584 RequestsHandled = requestsHandled;
585 }
266 } 586 }
267 } 587 }
268} 588}
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
index 1f1568f..0c632b1 100644
--- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
@@ -44,11 +44,12 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")] 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")]
45 public class DAExampleModule : INonSharedRegionModule 45 public class DAExampleModule : INonSharedRegionModule
46 { 46 {
47// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private static readonly bool ENABLED = false; // enable for testing 49 private readonly bool ENABLED = false; // enable for testing
50 50
51 public const string DANamespace = "DAExample Module"; 51 public const string Namespace = "Example";
52 public const string StoreName = "DA";
52 53
53 protected Scene m_scene; 54 protected Scene m_scene;
54 protected IDialogModule m_dialogMod; 55 protected IDialogModule m_dialogMod;
@@ -65,6 +66,8 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
65 m_scene = scene; 66 m_scene = scene;
66 m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove; 67 m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove;
67 m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>(); 68 m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>();
69
70 m_log.DebugFormat("[DA EXAMPLE MODULE]: Added region {0}", m_scene.Name);
68 } 71 }
69 } 72 }
70 73
@@ -91,7 +94,7 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
91 if (sop == null) 94 if (sop == null)
92 return true; 95 return true;
93 96
94 if (!sop.DynAttrs.TryGetValue(DANamespace, out attrs)) 97 if (!sop.DynAttrs.TryGetStore(Namespace, StoreName, out attrs))
95 attrs = new OSDMap(); 98 attrs = new OSDMap();
96 99
97 OSDInteger newValue; 100 OSDInteger newValue;
@@ -106,12 +109,14 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
106 109
107 attrs["moves"] = newValue; 110 attrs["moves"] = newValue;
108 111
109 sop.DynAttrs[DANamespace] = attrs; 112 sop.DynAttrs.SetStore(Namespace, StoreName, attrs);
110 } 113 }
111 114
112 sop.ParentGroup.HasGroupChanged = true; 115 sop.ParentGroup.HasGroupChanged = true;
113 116
114 m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue)); 117 string msg = string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue);
118 m_log.DebugFormat("[DA EXAMPLE MODULE]: {0}", msg);
119 m_dialogMod.SendGeneralAlert(msg);
115 120
116 return true; 121 return true;
117 } 122 }
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
index 650aa35..166a994 100644
--- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
@@ -64,8 +64,8 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
64 64
65 private Scene m_scene; 65 private Scene m_scene;
66 private IDialogModule m_dialogMod; 66 private IDialogModule m_dialogMod;
67 67
68 public string Name { get { return "DOExample Module"; } } 68 public string Name { get { return "DO"; } }
69 public Type ReplaceableInterface { get { return null; } } 69 public Type ReplaceableInterface { get { return null; } }
70 70
71 public void Initialise(IConfigSource source) {} 71 public void Initialise(IConfigSource source) {}
@@ -106,7 +106,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
106 106
107// Console.WriteLine("Here for {0}", so.Name); 107// Console.WriteLine("Here for {0}", so.Name);
108 108
109 if (rootPart.DynAttrs.TryGetValue(DAExampleModule.DANamespace, out attrs)) 109 if (rootPart.DynAttrs.TryGetStore(DAExampleModule.Namespace, DAExampleModule.StoreName, out attrs))
110 { 110 {
111 movesSoFar = attrs["moves"].AsInteger(); 111 movesSoFar = attrs["moves"].AsInteger();
112 112
@@ -114,7 +114,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
114 "[DO EXAMPLE MODULE]: Found saved moves {0} for {1} in {2}", movesSoFar, so.Name, m_scene.Name); 114 "[DO EXAMPLE MODULE]: Found saved moves {0} for {1} in {2}", movesSoFar, so.Name, m_scene.Name);
115 } 115 }
116 116
117 rootPart.DynObjs.Add(Name, new MyObject(movesSoFar)); 117 rootPart.DynObjs.Add(DAExampleModule.Namespace, Name, new MyObject(movesSoFar));
118 } 118 }
119 119
120 private bool OnSceneGroupMove(UUID groupId, Vector3 delta) 120 private bool OnSceneGroupMove(UUID groupId, Vector3 delta)
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index ed867b8..5fea0cf 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -51,11 +51,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EntityTransferModule")] 51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EntityTransferModule")]
52 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule 52 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]";
55 56
56 public const int DefaultMaxTransferDistance = 4095; 57 public const int DefaultMaxTransferDistance = 4095;
57 public const bool WaitForAgentArrivedAtDestinationDefault = true; 58 public const bool WaitForAgentArrivedAtDestinationDefault = true;
58 59
60 public string OutgoingTransferVersionName { get; set; }
61
62 /// <summary>
63 /// Determine the maximum entity transfer version we will use for teleports.
64 /// </summary>
65 public float MaxOutgoingTransferVersion { get; set; }
66
59 /// <summary> 67 /// <summary>
60 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. 68 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer.
61 /// </summary> 69 /// </summary>
@@ -151,9 +159,39 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
151 /// <param name="source"></param> 159 /// <param name="source"></param>
152 protected virtual void InitialiseCommon(IConfigSource source) 160 protected virtual void InitialiseCommon(IConfigSource source)
153 { 161 {
162 string transferVersionName = "SIMULATION";
163 float maxTransferVersion = 0.2f;
164
154 IConfig transferConfig = source.Configs["EntityTransfer"]; 165 IConfig transferConfig = source.Configs["EntityTransfer"];
155 if (transferConfig != null) 166 if (transferConfig != null)
156 { 167 {
168 string rawVersion
169 = transferConfig.GetString(
170 "MaxOutgoingTransferVersion",
171 string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
172
173 string[] rawVersionComponents = rawVersion.Split(new char[] { '/' });
174
175 bool versionValid = false;
176
177 if (rawVersionComponents.Length >= 2)
178 versionValid = float.TryParse(rawVersionComponents[1], out maxTransferVersion);
179
180 if (!versionValid)
181 {
182 m_log.ErrorFormat(
183 "[ENTITY TRANSFER MODULE]: MaxOutgoingTransferVersion {0} is invalid, using {1}",
184 rawVersion, string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
185 }
186 else
187 {
188 transferVersionName = rawVersionComponents[0];
189
190 m_log.InfoFormat(
191 "[ENTITY TRANSFER MODULE]: MaxOutgoingTransferVersion set to {0}",
192 string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
193 }
194
157 DisableInterRegionTeleportCancellation 195 DisableInterRegionTeleportCancellation
158 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false); 196 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false);
159 197
@@ -167,6 +205,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
167 MaxTransferDistance = DefaultMaxTransferDistance; 205 MaxTransferDistance = DefaultMaxTransferDistance;
168 } 206 }
169 207
208 OutgoingTransferVersionName = transferVersionName;
209 MaxOutgoingTransferVersion = maxTransferVersion;
210
170 m_entityTransferStateMachine = new EntityTransferStateMachine(this); 211 m_entityTransferStateMachine = new EntityTransferStateMachine(this);
171 212
172 m_Enabled = true; 213 m_Enabled = true;
@@ -280,10 +321,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
280 321
281 private void OnConnectionClosed(IClientAPI client) 322 private void OnConnectionClosed(IClientAPI client)
282 { 323 {
283 if (client.IsLoggingOut) 324 if (client.IsLoggingOut && m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting))
284 { 325 {
285 m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting);
286
287 m_log.DebugFormat( 326 m_log.DebugFormat(
288 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout", 327 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout",
289 client.Name, Scene.Name); 328 client.Name, Scene.Name);
@@ -318,7 +357,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
318 m_log.DebugFormat( 357 m_log.DebugFormat(
319 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.", 358 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.",
320 sp.Name, sp.UUID, position, regionHandle); 359 sp.Name, sp.UUID, position, regionHandle);
321 360
361 sp.ControllingClient.SendTeleportFailed("Previous teleport process incomplete. Please retry shortly.");
362
322 return; 363 return;
323 } 364 }
324 365
@@ -522,6 +563,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
522 /// </returns> 563 /// </returns>
523 private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion) 564 private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion)
524 { 565 {
566 if(MaxTransferDistance == 0)
567 return true;
568
525// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY); 569// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY);
526// 570//
527// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}", 571// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}",
@@ -623,7 +667,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
623 if (!sp.ValidateAttachments()) 667 if (!sp.ValidateAttachments())
624 m_log.DebugFormat( 668 m_log.DebugFormat(
625 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", 669 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
626 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); 670 sp.Name, sp.Scene.Name, finalDestination.RegionName);
627 671
628 string reason; 672 string reason;
629 string version; 673 string version;
@@ -634,7 +678,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
634 678
635 m_log.DebugFormat( 679 m_log.DebugFormat(
636 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", 680 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}",
637 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); 681 sp.Name, sp.Scene.Name, finalDestination.RegionName, reason);
638 682
639 return; 683 return;
640 } 684 }
@@ -644,7 +688,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
644 // as server attempts. 688 // as server attempts.
645 m_interRegionTeleportAttempts.Value++; 689 m_interRegionTeleportAttempts.Value++;
646 690
647 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); 691 m_log.DebugFormat(
692 "[ENTITY TRANSFER MODULE]: {0} max transfer version is {1}/{2}, {3} max version is {4}",
693 sp.Scene.Name, OutgoingTransferVersionName, MaxOutgoingTransferVersion, finalDestination.RegionName, version);
648 694
649 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 695 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
650 // both regions 696 // both regions
@@ -691,6 +737,29 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
691 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 737 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
692 } 738 }
693 739
740 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2 or we're forcing
741 // use of the earlier protocol
742 float versionNumber = 0.1f;
743 string[] versionComponents = version.Split(new char[] { '/' });
744 if (versionComponents.Length >= 2)
745 float.TryParse(versionComponents[1], out versionNumber);
746
747 if (versionNumber == 0.2f && MaxOutgoingTransferVersion >= versionNumber)
748 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
749 else
750 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
751 }
752
753 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
754 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason)
755 {
756 ulong destinationHandle = finalDestination.RegionHandle;
757 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
758
759 m_log.DebugFormat(
760 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}",
761 sp.Name, Scene.Name, finalDestination.RegionName);
762
694 // Let's create an agent there if one doesn't exist yet. 763 // Let's create an agent there if one doesn't exist yet.
695 // NOTE: logout will always be false for a non-HG teleport. 764 // NOTE: logout will always be false for a non-HG teleport.
696 bool logout = false; 765 bool logout = false;
@@ -712,7 +781,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
712 m_interRegionTeleportCancels.Value++; 781 m_interRegionTeleportCancels.Value++;
713 782
714 m_log.DebugFormat( 783 m_log.DebugFormat(
715 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", 784 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
716 sp.Name, finalDestination.RegionName, sp.Scene.Name); 785 sp.Name, finalDestination.RegionName, sp.Scene.Name);
717 786
718 return; 787 return;
@@ -734,11 +803,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
734 // OK, it got this agent. Let's close some child agents 803 // OK, it got this agent. Let's close some child agents
735 sp.CloseChildAgents(newRegionX, newRegionY); 804 sp.CloseChildAgents(newRegionX, newRegionY);
736 805
737 IClientIPEndpoint ipepClient; 806 IClientIPEndpoint ipepClient;
807 string capsPath = String.Empty;
738 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 808 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
739 { 809 {
740 m_log.DebugFormat( 810 m_log.DebugFormat(
741 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}", 811 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
742 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name); 812 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
743 813
744 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); 814 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
@@ -756,7 +826,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
756 // The EnableSimulator message makes the client establish a connection with the destination 826 // The EnableSimulator message makes the client establish a connection with the destination
757 // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the 827 // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the
758 // correct circuit code. 828 // correct circuit code.
759 m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID); 829 m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID,
830 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
831 m_log.DebugFormat("{0} Sent EnableSimulator. regName={1}, size=<{2},{3}>", LogHeader,
832 finalDestination.RegionName, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
760 833
761 // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination 834 // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination
762 // simulator to confirm that it has established communication with the viewer. 835 // simulator to confirm that it has established communication with the viewer.
@@ -766,7 +839,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
766 // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly 839 // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
767 // only on TeleportFinish). This is untested for region teleport between different simulators 840 // only on TeleportFinish). This is untested for region teleport between different simulators
768 // though this probably also works. 841 // though this probably also works.
769 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 842 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, finalDestination.RegionHandle,
843 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
770 } 844 }
771 else 845 else
772 { 846 {
@@ -785,10 +859,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
785 // Let's send a full update of the agent. This is a synchronous call. 859 // Let's send a full update of the agent. This is a synchronous call.
786 AgentData agent = new AgentData(); 860 AgentData agent = new AgentData();
787 sp.CopyTo(agent); 861 sp.CopyTo(agent);
788 agent.Position = position; 862 agent.Position = agentCircuit.startpos;
789 SetCallbackURL(agent, sp.Scene.RegionInfo); 863 SetCallbackURL(agent, sp.Scene.RegionInfo);
790 864
791 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
792 865
793 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to 866 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
794 // establish th econnection to the destination which makes it return true. 867 // establish th econnection to the destination which makes it return true.
@@ -821,10 +894,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
821 } 894 }
822 895
823 m_log.WarnFormat( 896 m_log.WarnFormat(
824 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", 897 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
825 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 898 sp.Name, finalDestination.RegionName, sp.Scene.Name);
826 899
827 Fail(sp, finalDestination, logout, "Connection between viewer and destination region could not be established."); 900 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
828 return; 901 return;
829 } 902 }
830 903
@@ -833,10 +906,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
833 m_interRegionTeleportCancels.Value++; 906 m_interRegionTeleportCancels.Value++;
834 907
835 m_log.DebugFormat( 908 m_log.DebugFormat(
836 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", 909 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
837 sp.Name, finalDestination.RegionName, sp.Scene.Name); 910 sp.Name, finalDestination.RegionName, sp.Scene.Name);
838 911
839 CleanupFailedInterRegionTeleport(sp, finalDestination); 912 CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination);
840 913
841 return; 914 return;
842 } 915 }
@@ -850,9 +923,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
850 // closes our existing agent which is still signalled as root. 923 // closes our existing agent which is still signalled as root.
851 sp.IsChildAgent = true; 924 sp.IsChildAgent = true;
852 925
926 // OK, send TPFinish to the client, so that it starts the process of contacting the destination region
853 if (m_eqModule != null) 927 if (m_eqModule != null)
854 { 928 {
855 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID); 929 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID,
930 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
856 } 931 }
857 else 932 else
858 { 933 {
@@ -879,8 +954,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
879 m_log.WarnFormat( 954 m_log.WarnFormat(
880 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", 955 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
881 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 956 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
882 957
883 Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion."); 958 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion.");
884 959
885 return; 960 return;
886 } 961 }
@@ -908,15 +983,190 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
908 983
909 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 984 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
910 { 985 {
986 if (!sp.Scene.IncomingPreCloseClient(sp))
987 return;
988
911 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before 989 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before
912 // they regard the new region as the current region after receiving the AgentMovementComplete 990 // they regard the new region as the current region after receiving the AgentMovementComplete
913 // response. If close is sent before then, it will cause the viewer to quit instead. 991 // response. If close is sent before then, it will cause the viewer to quit instead.
914 // 992 //
915 // This sleep can be increased if necessary. However, whilst it's active, 993 // This sleep can be increased if necessary. However, whilst it's active,
916 // an agent cannot teleport back to this region if it has teleported away. 994 // an agent cannot teleport back to this region if it has teleported away.
917 Thread.Sleep(3000); 995 Thread.Sleep(2000);
918 996
919 sp.Scene.IncomingCloseAgent(sp.UUID, false); 997 sp.Scene.CloseAgent(sp.UUID, false);
998 }
999 else
1000 {
1001 // now we have a child agent in this region.
1002 sp.Reset();
1003 }
1004 }
1005
1006 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
1007 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason)
1008 {
1009 ulong destinationHandle = finalDestination.RegionHandle;
1010 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1011
1012 // Let's create an agent there if one doesn't exist yet.
1013 // NOTE: logout will always be false for a non-HG teleport.
1014 bool logout = false;
1015 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
1016 {
1017 m_interRegionTeleportFailures.Value++;
1018
1019 sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
1020
1021 m_log.DebugFormat(
1022 "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
1023 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
1024
1025 return;
1026 }
1027
1028 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
1029 {
1030 m_interRegionTeleportCancels.Value++;
1031
1032 m_log.DebugFormat(
1033 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
1034 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1035
1036 return;
1037 }
1038 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
1039 {
1040 m_interRegionTeleportAborts.Value++;
1041
1042 m_log.DebugFormat(
1043 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
1044 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1045
1046 return;
1047 }
1048
1049 // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
1050 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
1051
1052 IClientIPEndpoint ipepClient;
1053 string capsPath = String.Empty;
1054 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
1055 {
1056 m_log.DebugFormat(
1057 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
1058 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
1059
1060 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
1061 #region IP Translation for NAT
1062 // Uses ipepClient above
1063 if (sp.ClientView.TryGet(out ipepClient))
1064 {
1065 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
1066 }
1067 #endregion
1068 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1069 }
1070 else
1071 {
1072 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
1073 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1074 }
1075
1076 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
1077 // where that neighbour simulator could otherwise request a child agent create on the source which then
1078 // closes our existing agent which is still signalled as root.
1079 //sp.IsChildAgent = true;
1080
1081 // New protocol: send TP Finish directly, without prior ES or EAC. That's what happens in the Linden grid
1082 if (m_eqModule != null)
1083 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID,
1084 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1085 else
1086 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
1087 teleportFlags, capsPath);
1088
1089 m_log.DebugFormat(
1090 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
1091 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
1092
1093 // Let's send a full update of the agent.
1094 AgentData agent = new AgentData();
1095 sp.CopyTo(agent);
1096 agent.Position = agentCircuit.startpos;
1097 agent.SenderWantsToWaitForRoot = true;
1098 //SetCallbackURL(agent, sp.Scene.RegionInfo);
1099
1100 // Reset the do not close flag. This must be done before the destination opens child connections (here
1101 // triggered by UpdateAgent) to avoid race conditions. However, we also want to reset it as late as possible
1102 // to avoid a situation where an unexpectedly early call to Scene.NewUserConnection() wrongly results
1103 // in no close.
1104 sp.DoNotCloseAfterTeleport = false;
1105
1106 // Send the Update. If this returns true, we know the client has contacted the destination
1107 // via CompleteMovementIntoRegion, so we can let go.
1108 // If it returns false, something went wrong, and we need to abort.
1109 if (!UpdateAgent(reg, finalDestination, agent, sp))
1110 {
1111 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
1112 {
1113 m_interRegionTeleportAborts.Value++;
1114
1115 m_log.DebugFormat(
1116 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
1117 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1118
1119 return;
1120 }
1121
1122 m_log.WarnFormat(
1123 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
1124 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1125
1126 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
1127 return;
1128 }
1129
1130 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1131
1132 // Need to signal neighbours whether child agents may need closing irrespective of whether this
1133 // one needed closing. We also need to close child agents as quickly as possible to avoid complicated
1134 // race conditions with rapid agent releporting (e.g. from A1 to a non-neighbour B, back
1135 // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex
1136 // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are
1137 // abandoned without proper close by viewer but then re-used by an incoming connection.
1138 sp.CloseChildAgents(newRegionX, newRegionY);
1139
1140 // May need to logout or other cleanup
1141 AgentHasMovedAway(sp, logout);
1142
1143 // Well, this is it. The agent is over there.
1144 KillEntity(sp.Scene, sp.LocalId);
1145
1146 // Now let's make it officially a child agent
1147 sp.MakeChildAgent();
1148
1149 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1150 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
1151 {
1152 if (!sp.Scene.IncomingPreCloseClient(sp))
1153 return;
1154
1155 // RED ALERT!!!!
1156 // PLEASE DO NOT DECREASE THIS WAIT TIME UNDER ANY CIRCUMSTANCES.
1157 // THE VIEWERS SEEM TO NEED SOME TIME AFTER RECEIVING MoveAgentIntoRegion
1158 // BEFORE THEY SETTLE IN THE NEW REGION.
1159 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR
1160 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS.
1161 Thread.Sleep(15000);
1162
1163 // OK, it got this agent. Let's close everything
1164 // If we shouldn't close the agent due to some other region renewing the connection
1165 // then this will be handled in IncomingCloseAgent under lock conditions
1166 m_log.DebugFormat(
1167 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
1168
1169 sp.Scene.CloseAgent(sp.UUID, false);
920 } 1170 }
921 else 1171 else
922 { 1172 {
@@ -934,17 +1184,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
934 /// <remarks> 1184 /// <remarks>
935 /// <param name='sp'> </param> 1185 /// <param name='sp'> </param>
936 /// <param name='finalDestination'></param> 1186 /// <param name='finalDestination'></param>
937 protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) 1187 protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, string auth_token, GridRegion finalDestination)
938 { 1188 {
939 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); 1189 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
940 1190
941 sp.IsChildAgent = false; 1191 if (sp.IsChildAgent) // We had set it to child before attempted TP (V1)
942 ReInstantiateScripts(sp); 1192 {
943 1193 sp.IsChildAgent = false;
944 EnableChildAgents(sp); 1194 ReInstantiateScripts(sp);
945 1195
1196 EnableChildAgents(sp);
1197 }
946 // Finally, kill the agent we just created at the destination. 1198 // Finally, kill the agent we just created at the destination.
947 Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); 1199 // XXX: Possibly this should be done asynchronously.
1200 Scene.SimulationService.CloseAgent(finalDestination, sp.UUID, auth_token);
948 } 1201 }
949 1202
950 /// <summary> 1203 /// <summary>
@@ -954,9 +1207,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
954 /// <param name='finalDestination'></param> 1207 /// <param name='finalDestination'></param>
955 /// <param name='logout'></param> 1208 /// <param name='logout'></param>
956 /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param> 1209 /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param>
957 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason) 1210 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string auth_code, string reason)
958 { 1211 {
959 CleanupFailedInterRegionTeleport(sp, finalDestination); 1212 CleanupFailedInterRegionTeleport(sp, auth_code, finalDestination);
960 1213
961 m_interRegionTeleportFailures.Value++; 1214 m_interRegionTeleportFailures.Value++;
962 1215
@@ -1132,7 +1385,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1132 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos) 1385 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos)
1133 { 1386 {
1134 version = String.Empty; 1387 version = String.Empty;
1135 newpos = new Vector3(pos.X, pos.Y, pos.Z); 1388 newpos = pos;
1136 1389
1137// m_log.DebugFormat( 1390// m_log.DebugFormat(
1138// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1391// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
@@ -1471,11 +1724,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1471 if (m_eqModule != null) 1724 if (m_eqModule != null)
1472 { 1725 {
1473 m_eqModule.CrossRegion( 1726 m_eqModule.CrossRegion(
1474 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, 1727 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */,
1475 capsPath, agent.UUID, agent.ControllingClient.SessionId); 1728 neighbourRegion.ExternalEndPoint,
1729 capsPath, agent.UUID, agent.ControllingClient.SessionId,
1730 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1476 } 1731 }
1477 else 1732 else
1478 { 1733 {
1734 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader);
1479 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, 1735 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint,
1480 capsPath); 1736 capsPath);
1481 } 1737 }
@@ -1654,10 +1910,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1654 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles); 1910 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1655 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles); 1911 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1656 1912
1657 //Dump("Current Neighbors", neighbourHandles); 1913// Dump("Current Neighbors", neighbourHandles);
1658 //Dump("Previous Neighbours", previousRegionNeighbourHandles); 1914// Dump("Previous Neighbours", previousRegionNeighbourHandles);
1659 //Dump("New Neighbours", newRegions); 1915// Dump("New Neighbours", newRegions);
1660 //Dump("Old Neighbours", oldRegions); 1916// Dump("Old Neighbours", oldRegions);
1661 1917
1662 /// Update the scene presence's known regions here on this region 1918 /// Update the scene presence's known regions here on this region
1663 sp.DropOldNeighbours(oldRegions); 1919 sp.DropOldNeighbours(oldRegions);
@@ -1665,8 +1921,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1665 /// Collect as many seeds as possible 1921 /// Collect as many seeds as possible
1666 Dictionary<ulong, string> seeds; 1922 Dictionary<ulong, string> seeds;
1667 if (sp.Scene.CapsModule != null) 1923 if (sp.Scene.CapsModule != null)
1668 seeds 1924 seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1669 = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1670 else 1925 else
1671 seeds = new Dictionary<ulong, string>(); 1926 seeds = new Dictionary<ulong, string>();
1672 1927
@@ -1736,6 +1991,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1736 newAgent = true; 1991 newAgent = true;
1737 else 1992 else
1738 newAgent = false; 1993 newAgent = false;
1994// continue;
1739 1995
1740 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 1996 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle)
1741 { 1997 {
@@ -1841,12 +2097,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1841 } 2097 }
1842 #endregion 2098 #endregion
1843 2099
1844 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: {0} is sending {1} EnableSimulator for neighbour region {2} @ {3} " + 2100 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " +
1845 "and EstablishAgentCommunication with seed cap {4}", 2101 "and EstablishAgentCommunication with seed cap {8}", LogHeader,
1846 scene.RegionInfo.RegionName, sp.Name, reg.RegionName, reg.RegionHandle, capsPath); 2102 scene.RegionInfo.RegionName, sp.Name,
2103 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY , capsPath);
1847 2104
1848 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID); 2105 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY);
1849 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 2106 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY);
1850 } 2107 }
1851 else 2108 else
1852 { 2109 {
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index d372c0e..7abdc21 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 54
55 private int m_levelHGTeleport = 0; 55 private int m_levelHGTeleport = 0;
56 private string m_ThisHomeURI;
56 57
57 private GatekeeperServiceConnector m_GatekeeperConnector; 58 private GatekeeperServiceConnector m_GatekeeperConnector;
59 private IUserAgentService m_UAS;
58 60
59 protected bool m_RestrictAppearanceAbroad; 61 protected bool m_RestrictAppearanceAbroad;
60 protected string m_AccountName; 62 protected string m_AccountName;
@@ -143,6 +145,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
143 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); 145 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
144 } 146 }
145 } 147 }
148
149 moduleConfig = source.Configs["Hypergrid"];
150 if (moduleConfig != null)
151 {
152 m_ThisHomeURI = moduleConfig.GetString("HomeURI", string.Empty);
153 if (m_ThisHomeURI != string.Empty && !m_ThisHomeURI.EndsWith("/"))
154 m_ThisHomeURI += '/';
155 }
146 } 156 }
147 157
148 public override void AddRegion(Scene scene) 158 public override void AddRegion(Scene scene)
@@ -161,22 +171,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
161 if (!so.IsAttachment) 171 if (!so.IsAttachment)
162 return; 172 return;
163 173
164 if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar)) 174 if (so.AttachedAvatar == UUID.Zero || Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar))
165 return; 175 return;
166 176
167 // foreign user 177 // foreign user
168 AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar); 178 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar);
169 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) 179 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
170 { 180 {
171 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 181 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
172 { 182 {
173 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 183 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
174 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); 184 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url);
175 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 185 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
176 HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url); 186 HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url);
177 uuidGatherer.GatherAssetUuids(so, ids); 187 uuidGatherer.GatherAssetUuids(so, ids);
178 188
179 foreach (KeyValuePair<UUID, AssetType> kvp in ids) 189 foreach (KeyValuePair<UUID, sbyte> kvp in ids)
180 uuidGatherer.FetchAsset(kvp.Key); 190 uuidGatherer.FetchAsset(kvp.Key);
181 } 191 }
182 } 192 }
@@ -194,7 +204,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
194 base.RegionLoaded(scene); 204 base.RegionLoaded(scene);
195 205
196 if (m_Enabled) 206 if (m_Enabled)
207 {
197 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService); 208 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
209 m_UAS = scene.RequestModuleInterface<IUserAgentService>();
210 if (m_UAS == null)
211 m_UAS = new UserAgentServiceConnector(m_ThisHomeURI);
212
213 }
198 } 214 }
199 215
200 public override void RemoveRegion(Scene scene) 216 public override void RemoveRegion(Scene scene)
@@ -272,8 +288,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
272 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI")) 288 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
273 { 289 {
274 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString(); 290 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
275 IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver); 291 IUserAgentService connector;
276 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason); 292
293 if (userAgentDriver.Equals(m_ThisHomeURI) && m_UAS != null)
294 connector = m_UAS;
295 else
296 connector = new UserAgentServiceConnector(userAgentDriver);
297
298 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, false, out reason);
277 logout = success; // flag for later logout from this grid; this is an HG TP 299 logout = success; // flag for later logout from this grid; this is an HG TP
278 300
279 if (success) 301 if (success)
@@ -552,12 +574,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
552 if (uMan != null && uMan.IsLocalGridUser(obj.AgentId)) 574 if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
553 { 575 {
554 // local grid user 576 // local grid user
577 m_UAS.LogoutAgent(obj.AgentId, obj.SessionId);
555 return; 578 return;
556 } 579 }
557 580
558 AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode); 581 AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
559 582 if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("HomeURI"))
560 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
561 { 583 {
562 string url = aCircuit.ServiceURLs["HomeURI"].ToString(); 584 string url = aCircuit.ServiceURLs["HomeURI"].ToString();
563 IUserAgentService security = new UserAgentServiceConnector(url); 585 IUserAgentService security = new UserAgentServiceConnector(url);
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index 7871eda..d4fb1ba 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -73,6 +73,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
73 73
74 private AssetMetadata FetchMetadata(string url, UUID assetID) 74 private AssetMetadata FetchMetadata(string url, UUID assetID)
75 { 75 {
76 if (string.IsNullOrEmpty(url))
77 return null;
78
76 if (!url.EndsWith("/") && !url.EndsWith("=")) 79 if (!url.EndsWith("/") && !url.EndsWith("="))
77 url = url + "/"; 80 url = url + "/";
78 81
@@ -92,6 +95,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
92 AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); 95 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
93 if (asset == null) 96 if (asset == null)
94 { 97 {
98 if (string.IsNullOrEmpty(url))
99 return null;
100
95 if (!url.EndsWith("/") && !url.EndsWith("=")) 101 if (!url.EndsWith("/") && !url.EndsWith("="))
96 url = url + "/"; 102 url = url + "/";
97 103
@@ -109,6 +115,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
109 115
110 public bool PostAsset(string url, AssetBase asset) 116 public bool PostAsset(string url, AssetBase asset)
111 { 117 {
118 if (string.IsNullOrEmpty(url))
119 return false;
120
112 if (asset != null) 121 if (asset != null)
113 { 122 {
114 if (!url.EndsWith("/") && !url.EndsWith("=")) 123 if (!url.EndsWith("/") && !url.EndsWith("="))
@@ -165,7 +174,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
165 174
166 private void AdjustIdentifiers(AssetMetadata meta) 175 private void AdjustIdentifiers(AssetMetadata meta)
167 { 176 {
168 if (meta.CreatorID != null && meta.CreatorID != string.Empty) 177 if (!string.IsNullOrEmpty(meta.CreatorID))
169 { 178 {
170 UUID uuid = UUID.Zero; 179 UUID uuid = UUID.Zero;
171 UUID.TryParse(meta.CreatorID, out uuid); 180 UUID.TryParse(meta.CreatorID, out uuid);
@@ -251,9 +260,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
251 260
252 // The act of gathering UUIDs downloads some assets from the remote server 261 // The act of gathering UUIDs downloads some assets from the remote server
253 // but not all... 262 // but not all...
254 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 263 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
255 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); 264 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
256 uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); 265 uuidGatherer.GatherAssetUuids(assetID, meta.Type, ids);
257 m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count); 266 m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count);
258 bool success = true; 267 bool success = true;
259 foreach (UUID uuid in ids.Keys) 268 foreach (UUID uuid in ids.Keys)
@@ -277,9 +286,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
277 AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); 286 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
278 if (asset != null) 287 if (asset != null)
279 { 288 {
280 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 289 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
281 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); 290 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty);
282 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); 291 uuidGatherer.GatherAssetUuids(asset.FullID, asset.Type, ids);
283 bool success = false; 292 bool success = false;
284 foreach (UUID uuid in ids.Keys) 293 foreach (UUID uuid in ids.Keys)
285 { 294 {
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index b2b628d..ce7ed26 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -62,6 +62,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
62 private string m_ThisGatekeeper; 62 private string m_ThisGatekeeper;
63 private bool m_RestrictInventoryAccessAbroad; 63 private bool m_RestrictInventoryAccessAbroad;
64 64
65 private bool m_bypassPermissions = true;
66
65// private bool m_Initialized = false; 67// private bool m_Initialized = false;
66 68
67 #region INonSharedRegionModule 69 #region INonSharedRegionModule
@@ -100,6 +102,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
100 } 102 }
101 else 103 else
102 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); 104 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
105
106 m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(source, "serverside_object_permissions",
107 new string[] { "Startup", "Permissions" }, true);
108
103 } 109 }
104 } 110 }
105 } 111 }
@@ -114,6 +120,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
114 scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem; 120 scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem;
115 scene.EventManager.OnTeleportStart += TeleportStart; 121 scene.EventManager.OnTeleportStart += TeleportStart;
116 scene.EventManager.OnTeleportFail += TeleportFail; 122 scene.EventManager.OnTeleportFail += TeleportFail;
123
124 // We're fgoing to enforce some stricter permissions if Outbound is false
125 scene.Permissions.OnTakeObject += CanTakeObject;
126 scene.Permissions.OnTakeCopyObject += CanTakeObject;
127 scene.Permissions.OnTransferUserInventory += OnTransferUserInventory;
117 } 128 }
118 129
119 #endregion 130 #endregion
@@ -135,7 +146,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
135 if (sp is ScenePresence) 146 if (sp is ScenePresence)
136 { 147 {
137 AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId); 148 AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId);
138 if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) 149 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
139 { 150 {
140 if (m_RestrictInventoryAccessAbroad) 151 if (m_RestrictInventoryAccessAbroad)
141 { 152 {
@@ -185,8 +196,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
185 } 196 }
186 } 197 }
187 198
188 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) 199 public void UploadInventoryItem(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel)
189 { 200 {
201 if (type == AssetType.Link)
202 return;
203
190 string userAssetServer = string.Empty; 204 string userAssetServer = string.Empty;
191 if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) 205 if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
192 { 206 {
@@ -221,7 +235,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
221 { 235 {
222 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data); 236 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data);
223 237
224 UploadInventoryItem(remoteClient.AgentId, newAssetID, "", 0); 238 UploadInventoryItem(remoteClient.AgentId, AssetType.Unknown, newAssetID, "", 0);
225 239
226 return newAssetID; 240 return newAssetID;
227 } 241 }
@@ -232,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
232 protected override void ExportAsset(UUID agentID, UUID assetID) 246 protected override void ExportAsset(UUID agentID, UUID assetID)
233 { 247 {
234 if (!assetID.Equals(UUID.Zero)) 248 if (!assetID.Equals(UUID.Zero))
235 UploadInventoryItem(agentID, assetID, "", 0); 249 UploadInventoryItem(agentID, AssetType.Unknown, assetID, "", 0);
236 else 250 else
237 m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); 251 m_log.Debug("[HGScene]: Scene.Inventory did not create asset");
238 } 252 }
@@ -244,7 +258,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
244 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 258 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
245 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 259 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
246 { 260 {
247 m_log.DebugFormat("[HGScene] RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID); 261 m_log.DebugFormat("[HGScene]: RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID);
248 262
249 //if (fromTaskID.Equals(UUID.Zero)) 263 //if (fromTaskID.Equals(UUID.Zero))
250 //{ 264 //{
@@ -297,7 +311,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
297 if (m_Scene.TryGetScenePresence(userID, out sp)) 311 if (m_Scene.TryGetScenePresence(userID, out sp))
298 { 312 {
299 AgentCircuitData aCircuit = m_Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 313 AgentCircuitData aCircuit = m_Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
300 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 314 if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
301 { 315 {
302 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 316 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString();
303 assetServerURL = assetServerURL.Trim(new char[] { '/' }); 317 assetServerURL = assetServerURL.Trim(new char[] { '/' });
@@ -348,7 +362,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
348 InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId); 362 InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId);
349 InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID); 363 InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID);
350 364
351 inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); 365 List<InventoryFolderBase> keep = new List<InventoryFolderBase>();
366
367 foreach (InventoryFolderBase f in content.Folders)
368 {
369 if (f.Name != "My Suitcase" && f.Name != "Current Outfit")
370 keep.Add(f);
371 }
372
373 inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray());
352 } 374 }
353 } 375 }
354 } 376 }
@@ -381,7 +403,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
381 403
382 foreach (InventoryFolderBase f in content.Folders) 404 foreach (InventoryFolderBase f in content.Folders)
383 { 405 {
384 if (f.Name != "My Suitcase") 406 if (f.Name != "My Suitcase" && f.Name != "Current Outfit")
385 { 407 {
386 f.Name = f.Name + " (Unavailable)"; 408 f.Name = f.Name + " (Unavailable)";
387 keep.Add(f); 409 keep.Add(f);
@@ -406,5 +428,36 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
406 } 428 }
407 429
408 #endregion 430 #endregion
431
432 #region Permissions
433
434 private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene)
435 {
436 if (m_bypassPermissions) return true;
437
438 if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(stealer))
439 {
440 SceneObjectGroup sog = null;
441 if (m_Scene.TryGetSceneObjectGroup(objectID, out sog) && sog.OwnerID == stealer)
442 return true;
443
444 return false;
445 }
446
447 return true;
448 }
449
450 private bool OnTransferUserInventory(UUID itemID, UUID userID, UUID recipientID)
451 {
452 if (m_bypassPermissions) return true;
453
454 if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(recipientID))
455 return false;
456
457 return true;
458 }
459
460
461 #endregion
409 } 462 }
410} \ No newline at end of file 463} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index d09ea3e..fadcd5e 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -358,7 +358,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
358 bool asAttachment) 358 bool asAttachment)
359 { 359 {
360 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); 360 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
361 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); 361// Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
362 362
363 foreach (SceneObjectGroup objectGroup in objlist) 363 foreach (SceneObjectGroup objectGroup in objlist)
364 { 364 {
@@ -379,7 +379,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
379 objectGroup.AbsolutePosition.Z); 379 objectGroup.AbsolutePosition.Z);
380 380
381 Quaternion inventoryStoredRotation = objectGroup.GroupRotation; 381 Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
382 originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; 382 //originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
383 383
384 // Restore attachment data after trip through the sim 384 // Restore attachment data after trip through the sim
385 if (objectGroup.RootPart.AttachPoint > 0) 385 if (objectGroup.RootPart.AttachPoint > 0)
@@ -390,9 +390,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
390 390
391 // Trees could be attached and it's been done, but it makes 391 // Trees could be attached and it's been done, but it makes
392 // no sense. State must be preserved because it's the tree type 392 // no sense. State must be preserved because it's the tree type
393 if (objectGroup.RootPart.Shape.PCode != (byte)PCode.Tree && 393 if (objectGroup.RootPart.Shape.PCode != (byte) PCode.Tree &&
394 objectGroup.RootPart.Shape.PCode != (byte)PCode.NewTree) 394 objectGroup.RootPart.Shape.PCode != (byte) PCode.NewTree)
395 {
395 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint; 396 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint;
397 if (objectGroup.RootPart.AttachPoint > 0)
398 objectGroup.RootPart.Shape.LastAttachPoint = objectGroup.RootPart.AttachPoint;
399 }
396 400
397 objectGroup.AbsolutePosition = inventoryStoredPosition; 401 objectGroup.AbsolutePosition = inventoryStoredPosition;
398 objectGroup.RootPart.RotationOffset = inventoryStoredRotation; 402 objectGroup.RootPart.RotationOffset = inventoryStoredRotation;
@@ -423,9 +427,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
423 else 427 else
424 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); 428 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
425 429
426 // Restore the position of each group now that it has been stored to inventory. 430// // Restore the position of each group now that it has been stored to inventory.
427 foreach (SceneObjectGroup objectGroup in objlist) 431// foreach (SceneObjectGroup objectGroup in objlist)
428 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; 432// objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
429 433
430 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); 434 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
431 435
@@ -435,17 +439,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
435 439
436 if (item == null) 440 if (item == null)
437 return null; 441 return null;
442
443 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
444 item.CreatorData = objlist[0].RootPart.CreatorData;
438 445
439 // Can't know creator is the same, so null it in inventory
440 if (objlist.Count > 1) 446 if (objlist.Count > 1)
441 { 447 {
442 item.CreatorId = UUID.Zero.ToString();
443 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; 448 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
449
450 // If the objects have different creators then don't specify a creator at all
451 foreach (SceneObjectGroup objectGroup in objlist)
452 {
453 if ((objectGroup.RootPart.CreatorID.ToString() != item.CreatorId)
454 || (objectGroup.RootPart.CreatorData.ToString() != item.CreatorData))
455 {
456 item.CreatorId = UUID.Zero.ToString();
457 item.CreatorData = string.Empty;
458 break;
459 }
460 }
444 } 461 }
445 else 462 else
446 { 463 {
447 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
448 item.CreatorData = objlist[0].RootPart.CreatorData;
449 item.SaleType = objlist[0].RootPart.ObjectSaleType; 464 item.SaleType = objlist[0].RootPart.ObjectSaleType;
450 item.SalePrice = objlist[0].RootPart.SalePrice; 465 item.SalePrice = objlist[0].RootPart.SalePrice;
451 } 466 }
@@ -466,13 +481,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
466 } 481 }
467 else 482 else
468 { 483 {
469 AddPermissions(item, objlist[0], objlist, remoteClient);
470
471 item.CreationDate = Util.UnixTimeSinceEpoch(); 484 item.CreationDate = Util.UnixTimeSinceEpoch();
472 item.Description = asset.Description; 485 item.Description = asset.Description;
473 item.Name = asset.Name; 486 item.Name = asset.Name;
474 item.AssetType = asset.Type; 487 item.AssetType = asset.Type;
475 488
489 AddPermissions(item, objlist[0], objlist, remoteClient);
490
476 m_Scene.AddInventoryItem(item); 491 m_Scene.AddInventoryItem(item);
477 492
478 if (remoteClient != null && item.Owner == remoteClient.AgentId) 493 if (remoteClient != null && item.Owner == remoteClient.AgentId)
@@ -527,16 +542,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
527 } 542 }
528 effectivePerms |= (uint)PermissionMask.Move; 543 effectivePerms |= (uint)PermissionMask.Move;
529 544
545 //PermissionsUtil.LogPermissions(item.Name, "Before AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions);
546
530 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) 547 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
531 { 548 {
532 uint perms = effectivePerms; 549 uint perms = effectivePerms;
533 uint nextPerms = (perms & 7) << 13; 550 PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms);
534 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
535 perms &= ~(uint)PermissionMask.Copy;
536 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
537 perms &= ~(uint)PermissionMask.Transfer;
538 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
539 perms &= ~(uint)PermissionMask.Modify;
540 551
541 item.BasePermissions = perms & so.RootPart.NextOwnerMask; 552 item.BasePermissions = perms & so.RootPart.NextOwnerMask;
542 item.CurrentPermissions = item.BasePermissions; 553 item.CurrentPermissions = item.BasePermissions;
@@ -544,10 +555,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
544 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask; 555 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask;
545 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask; 556 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask;
546 557
547 // Magic number badness. Maybe this deserves an enum. 558 // apply next owner perms on rez
548 // bit 4 (16) is the "Slam" bit, it means treat as passed 559 item.CurrentPermissions |= SceneObjectGroup.SLAM;
549 // and apply next owner perms on rez
550 item.CurrentPermissions |= 16; // Slam!
551 } 560 }
552 else 561 else
553 { 562 {
@@ -564,8 +573,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
564 (uint)PermissionMask.Move | 573 (uint)PermissionMask.Move |
565 (uint)PermissionMask.Export | 574 (uint)PermissionMask.Export |
566 7); // Preserve folded permissions 575 7); // Preserve folded permissions
567 } 576 }
568 577
578 //PermissionsUtil.LogPermissions(item.Name, "After AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions);
579
569 return item; 580 return item;
570 } 581 }
571 582
@@ -707,6 +718,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
707 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); 718 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID);
708 if (f != null) 719 if (f != null)
709 folder = m_Scene.InventoryService.GetFolder(f); 720 folder = m_Scene.InventoryService.GetFolder(f);
721
722 if(folder.Type == 14 || folder.Type == 16)
723 {
724 // folder.Type = 6;
725 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
726 }
710 } 727 }
711 } 728 }
712 729
@@ -779,83 +796,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
779 796
780 SceneObjectGroup group = null; 797 SceneObjectGroup group = null;
781 798
782 string xmlData = Utils.BytesToString(rezAsset.Data); 799 List<SceneObjectGroup> objlist;
783 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(); 800 List<Vector3> veclist;
784 List<Vector3> veclist = new List<Vector3>(); 801 Vector3 bbox;
802 float offsetHeight;
785 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 803 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
786 Vector3 pos; 804 Vector3 pos;
787 805
788 XmlDocument doc = new XmlDocument(); 806 bool single = m_Scene.GetObjectsToRez(rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight);
789 doc.LoadXml(xmlData);
790 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
791 Vector3 rez_pos;
792 if (e == null || attachment) // Single
793 {
794 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
795 if (!attachment)
796 {
797 g.RootPart.AttachPoint = g.RootPart.Shape.State;
798 g.RootPart.AttachOffset = g.AbsolutePosition;
799 g.RootPart.AttachRotation = g.GroupRotation;
800 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
801 g.RootPart.Shape.PCode != (byte)PCode.Tree)
802 g.RootPart.Shape.State = 0;
803 }
804 807
805 objlist.Add(g); 808 if (single)
806 veclist.Add(new Vector3(0, 0, 0)); 809 {
807
808 float offsetHeight = 0;
809 pos = m_Scene.GetNewRezLocation( 810 pos = m_Scene.GetNewRezLocation(
810 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 811 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
811 BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); 812 BypassRayCast, bRayEndIsIntersection, true, bbox, false);
812 pos.Z += offsetHeight; 813 pos.Z += offsetHeight;
813 rez_pos = pos;
814 } 814 }
815 else 815 else
816 { 816 {
817 XmlElement coll = (XmlElement)e;
818 float bx = Convert.ToSingle(coll.GetAttribute("x"));
819 float by = Convert.ToSingle(coll.GetAttribute("y"));
820 float bz = Convert.ToSingle(coll.GetAttribute("z"));
821 Vector3 bbox = new Vector3(bx, by, bz);
822
823 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, 817 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd,
824 RayTargetID, Quaternion.Identity, 818 RayTargetID, Quaternion.Identity,
825 BypassRayCast, bRayEndIsIntersection, true, 819 BypassRayCast, bRayEndIsIntersection, true,
826 bbox, false); 820 bbox, false);
827
828 rez_pos = pos;
829
830 pos -= bbox / 2; 821 pos -= bbox / 2;
831
832 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
833 foreach (XmlNode n in groups)
834 {
835 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
836 g.RootPart.AttachPoint = g.RootPart.Shape.State;
837 g.RootPart.AttachOffset = g.AbsolutePosition;
838 g.RootPart.AttachRotation = g.GroupRotation;
839 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
840 g.RootPart.Shape.PCode != (byte)PCode.Tree)
841 g.RootPart.Shape.State = 0;
842
843 objlist.Add(g);
844 XmlElement el = (XmlElement)n;
845
846 string rawX = el.GetAttribute("offsetx");
847 string rawY = el.GetAttribute("offsety");
848 string rawZ = el.GetAttribute("offsetz");
849//
850// m_log.DebugFormat(
851// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
852// g.Name, rawX, rawY, rawZ);
853
854 float x = Convert.ToSingle(rawX);
855 float y = Convert.ToSingle(rawY);
856 float z = Convert.ToSingle(rawZ);
857 veclist.Add(new Vector3(x, y, z));
858 }
859 } 822 }
860 823
861 int primcount = 0; 824 int primcount = 0;
@@ -863,7 +826,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
863 primcount += g.PrimCount; 826 primcount += g.PrimCount;
864 827
865 if (!m_Scene.Permissions.CanRezObject( 828 if (!m_Scene.Permissions.CanRezObject(
866 primcount, remoteClient.AgentId, rez_pos) 829 primcount, remoteClient.AgentId, pos)
867 && !attachment) 830 && !attachment)
868 { 831 {
869 // The client operates in no fail mode. It will 832 // The client operates in no fail mode. It will
@@ -880,7 +843,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
880 return null; 843 return null;
881 } 844 }
882 845
883 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, rez_pos, attachment)) 846 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
884 return null; 847 return null;
885 848
886 for (int i = 0; i < objlist.Count; i++) 849 for (int i = 0; i < objlist.Count; i++)
@@ -900,11 +863,23 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
900 m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3"); 863 m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3");
901 } 864 }
902 865
903 foreach (SceneObjectPart part in group.Parts) 866 // if this was previously an attachment and is now being rezzed,
867 // save the old attachment info.
868 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
904 { 869 {
905 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset. 870 group.RootPart.AttachedPos = group.AbsolutePosition;
906 part.LastOwnerID = part.OwnerID; 871 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
907 part.OwnerID = remoteClient.AgentId; 872 }
873
874 if (item == null)
875 {
876 // Change ownership. Normally this is done in DoPreRezWhenFromItem(), but in this case we must do it here.
877 foreach (SceneObjectPart part in group.Parts)
878 {
879 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset.
880 part.LastOwnerID = part.OwnerID;
881 part.OwnerID = remoteClient.AgentId;
882 }
908 } 883 }
909 884
910 if (!attachment) 885 if (!attachment)
@@ -979,10 +954,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
979 /// <param name="item"></param> 954 /// <param name="item"></param>
980 /// <param name="objlist"></param> 955 /// <param name="objlist"></param>
981 /// <param name="pos"></param> 956 /// <param name="pos"></param>
957 /// <param name="veclist">
958 /// List of vector position adjustments for a coalesced objects. For ordinary objects
959 /// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist
960 /// </param>
982 /// <param name="isAttachment"></param> 961 /// <param name="isAttachment"></param>
983 /// <returns>true if we can processed with rezzing, false if we need to abort</returns> 962 /// <returns>true if we can processed with rezzing, false if we need to abort</returns>
984 private bool DoPreRezWhenFromItem( 963 private bool DoPreRezWhenFromItem(
985 IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, Vector3 pos, bool isAttachment) 964 IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist,
965 Vector3 pos, List<Vector3> veclist, bool isAttachment)
986 { 966 {
987 UUID fromUserInventoryItemId = UUID.Zero; 967 UUID fromUserInventoryItemId = UUID.Zero;
988 968
@@ -1005,28 +985,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1005 } 985 }
1006 } 986 }
1007 987
1008 int primcount = 0; 988 for (int i = 0; i < objlist.Count; i++)
1009 foreach (SceneObjectGroup g in objlist)
1010 primcount += g.PrimCount;
1011
1012 if (!m_Scene.Permissions.CanRezObject(
1013 primcount, remoteClient.AgentId, pos)
1014 && !isAttachment)
1015 { 989 {
1016 // The client operates in no fail mode. It will 990 SceneObjectGroup g = objlist[i];
1017 // have already removed the item from the folder
1018 // if it's no copy.
1019 // Put it back if it's not an attachment
1020 //
1021 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
1022 remoteClient.SendBulkUpdateInventory(item);
1023 991
1024 ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); 992 if (!m_Scene.Permissions.CanRezObject(
1025 remoteClient.SendAlertMessage(string.Format( 993 g.PrimCount, remoteClient.AgentId, pos + veclist[i])
1026 "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", 994 && !isAttachment)
1027 item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.RegionInfo.RegionName)); 995 {
996 // The client operates in no fail mode. It will
997 // have already removed the item from the folder
998 // if it's no copy.
999 // Put it back if it's not an attachment
1000 //
1001 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
1002 remoteClient.SendBulkUpdateInventory(item);
1028 1003
1029 return false; 1004 ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
1005 remoteClient.SendAlertMessage(string.Format(
1006 "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.",
1007 item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name));
1008
1009 return false;
1010 }
1030 } 1011 }
1031 1012
1032 for (int i = 0; i < objlist.Count; i++) 1013 for (int i = 0; i < objlist.Count; i++)
@@ -1107,7 +1088,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1107 part.GroupMask = item.GroupPermissions; 1088 part.GroupMask = item.GroupPermissions;
1108 } 1089 }
1109 } 1090 }
1110 1091
1111 rootPart.TrimPermissions(); 1092 rootPart.TrimPermissions();
1112 1093
1113 if (isAttachment) 1094 if (isAttachment)
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
index d07cff4..69d7e16 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
@@ -176,7 +176,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
176 m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName); 176 m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName);
177 simpleName = GetInventoryPathFromName(simpleName); 177 simpleName = GetInventoryPathFromName(simpleName);
178 178
179 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName, false); 179 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene.InventoryService, m_MockScene.AssetService, m_MockScene.UserAccountService, uinfo, simpleName, iarFileName, false);
180 try 180 try
181 { 181 {
182 HashSet<InventoryNodeBase> nodes = archread.Execute(); 182 HashSet<InventoryNodeBase> nodes = archread.Execute();
@@ -185,7 +185,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
185 // didn't find the subfolder with the given name; place it on the top 185 // didn't find the subfolder with the given name; place it on the top
186 m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName); 186 m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName);
187 archread.Close(); 187 archread.Close();
188 archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, "/", iarFileName, false); 188 archread = new InventoryArchiveReadRequest(m_MockScene.InventoryService, m_MockScene.AssetService, m_MockScene.UserAccountService, uinfo, "/", iarFileName, false);
189 archread.Execute(); 189 archread.Execute();
190 } 190 }
191 191
diff --git a/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs b/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs
new file mode 100644
index 0000000..8838612
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs
@@ -0,0 +1,197 @@
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.IO;
30using System.Reflection;
31using System.Threading;
32
33using OpenSim.Framework;
34using OpenSim.Framework.Console;
35using OpenSim.Framework.Monitoring;
36using OpenSim.Region.ClientStack.LindenUDP;
37using OpenSim.Region.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Services.Connectors.Hypergrid;
42
43using OpenMetaverse;
44using OpenMetaverse.Packets;
45using log4net;
46using Nini.Config;
47using Mono.Addins;
48
49using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
50
51namespace OpenSim.Region.CoreModules.Framework.Search
52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BasicSearchModule")]
54 public class BasicSearchModule : ISharedRegionModule
55 {
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57
58 protected bool m_Enabled;
59 protected List<Scene> m_Scenes = new List<Scene>();
60
61 private IGroupsModule m_GroupsService = null;
62
63 #region ISharedRegionModule
64
65 public void Initialise(IConfigSource config)
66 {
67 string umanmod = config.Configs["Modules"].GetString("SearchModule", Name);
68 if (umanmod == Name)
69 {
70 m_Enabled = true;
71 m_log.DebugFormat("[BASIC SEARCH MODULE]: {0} is enabled", Name);
72 }
73 }
74
75 public bool IsSharedModule
76 {
77 get { return true; }
78 }
79
80 public virtual string Name
81 {
82 get { return "BasicSearchModule"; }
83 }
84
85 public Type ReplaceableInterface
86 {
87 get { return null; }
88 }
89
90 public void AddRegion(Scene scene)
91 {
92 if (m_Enabled)
93 {
94 m_Scenes.Add(scene);
95
96 scene.EventManager.OnMakeRootAgent += new Action<ScenePresence>(EventManager_OnMakeRootAgent);
97 scene.EventManager.OnMakeChildAgent += new EventManager.OnMakeChildAgentDelegate(EventManager_OnMakeChildAgent);
98 }
99 }
100
101 public void RemoveRegion(Scene scene)
102 {
103 if (m_Enabled)
104 {
105 m_Scenes.Remove(scene);
106
107 scene.EventManager.OnMakeRootAgent -= new Action<ScenePresence>(EventManager_OnMakeRootAgent);
108 scene.EventManager.OnMakeChildAgent -= new EventManager.OnMakeChildAgentDelegate(EventManager_OnMakeChildAgent);
109 }
110 }
111
112 public void RegionLoaded(Scene s)
113 {
114 if (!m_Enabled)
115 return;
116
117 if (m_GroupsService == null)
118 {
119 m_GroupsService = s.RequestModuleInterface<IGroupsModule>();
120
121 // No Groups Service Connector, then group search won't work...
122 if (m_GroupsService == null)
123 m_log.Warn("[BASIC SEARCH MODULE]: Could not get IGroupsModule");
124 }
125 }
126
127 public void PostInitialise()
128 {
129 }
130
131 public void Close()
132 {
133 m_Scenes.Clear();
134 }
135
136 #endregion ISharedRegionModule
137
138
139 #region Event Handlers
140
141 void EventManager_OnMakeRootAgent(ScenePresence sp)
142 {
143 sp.ControllingClient.OnDirFindQuery += OnDirFindQuery;
144 }
145
146 void EventManager_OnMakeChildAgent(ScenePresence sp)
147 {
148 sp.ControllingClient.OnDirFindQuery -= OnDirFindQuery;
149 }
150
151 void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart)
152 {
153 if (((DirFindFlags)queryFlags & DirFindFlags.People) == DirFindFlags.People)
154 {
155 if (string.IsNullOrEmpty(queryText))
156 remoteClient.SendDirPeopleReply(queryID, new DirPeopleReplyData[0]);
157
158 List<UserAccount> accounts = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, queryText);
159 DirPeopleReplyData[] hits = new DirPeopleReplyData[accounts.Count];
160 int i = 0;
161 foreach (UserAccount acc in accounts)
162 {
163 DirPeopleReplyData d = new DirPeopleReplyData();
164 d.agentID = acc.PrincipalID;
165 d.firstName = acc.FirstName;
166 d.lastName = acc.LastName;
167 d.online = false;
168
169 hits[i++] = d;
170 }
171
172 // TODO: This currently ignores pretty much all the query flags including Mature and sort order
173 remoteClient.SendDirPeopleReply(queryID, hits);
174 }
175 else if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups)
176 {
177 if (m_GroupsService == null)
178 {
179 m_log.Warn("[BASIC SEARCH MODULE]: Groups service is not available. Unable to search groups.");
180 remoteClient.SendAlertMessage("Groups search is not enabled");
181 return;
182 }
183
184 if (string.IsNullOrEmpty(queryText))
185 remoteClient.SendDirGroupsReply(queryID, new DirGroupsReplyData[0]);
186
187 // TODO: This currently ignores pretty much all the query flags including Mature and sort order
188 remoteClient.SendDirGroupsReply(queryID, m_GroupsService.FindGroups(remoteClient, queryText).ToArray());
189 }
190
191 }
192
193 #endregion Event Handlers
194
195 }
196
197} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
new file mode 100644
index 0000000..a70261e
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
@@ -0,0 +1,256 @@
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.Threading;
32using log4net;
33using Mono.Addins;
34using Nini.Config;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Framework.Monitoring;
39using OpenSim.Region.Framework.Scenes;
40using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41
42namespace OpenSim.Region.CoreModules.Framework
43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridServiceThrottleModule")]
45 public class ServiceThrottleModule : ISharedRegionModule, IServiceThrottleModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 private readonly List<Scene> m_scenes = new List<Scene>();
51 private System.Timers.Timer m_timer = new System.Timers.Timer();
52
53 private Queue<Action> m_RequestQueue = new Queue<Action>();
54 private Dictionary<string, List<string>> m_Pending = new Dictionary<string, List<string>>();
55 private int m_Interval;
56
57 #region ISharedRegionModule
58
59 public void Initialise(IConfigSource config)
60 {
61 m_Interval = Util.GetConfigVarFromSections<int>(config, "Interval", new string[] { "ServiceThrottle" }, 5000);
62
63 m_timer = new System.Timers.Timer();
64 m_timer.AutoReset = false;
65 m_timer.Enabled = true;
66 m_timer.Interval = 15000; // 15 secs at first
67 m_timer.Elapsed += ProcessQueue;
68 m_timer.Start();
69
70 //Watchdog.StartThread(
71 // ProcessQueue,
72 // "GridServiceRequestThread",
73 // ThreadPriority.BelowNormal,
74 // true,
75 // false);
76 }
77
78 public void AddRegion(Scene scene)
79 {
80 lock (m_scenes)
81 {
82 m_scenes.Add(scene);
83 scene.RegisterModuleInterface<IServiceThrottleModule>(this);
84 scene.EventManager.OnNewClient += OnNewClient;
85 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
86 }
87 }
88
89 public void RegionLoaded(Scene scene)
90 {
91 }
92
93 public void RemoveRegion(Scene scene)
94 {
95 lock (m_scenes)
96 {
97 m_scenes.Remove(scene);
98 scene.EventManager.OnNewClient -= OnNewClient;
99 }
100 }
101
102 public void PostInitialise()
103 {
104 }
105
106 public void Close()
107 {
108 }
109
110 public string Name
111 {
112 get { return "ServiceThrottleModule"; }
113 }
114
115 public Type ReplaceableInterface
116 {
117 get { return null; }
118 }
119
120 #endregion ISharedRegionMOdule
121
122 #region Events
123
124 void OnNewClient(IClientAPI client)
125 {
126 client.OnRegionHandleRequest += OnRegionHandleRequest;
127 }
128
129 void OnMakeRootAgent(ScenePresence obj)
130 {
131 lock (m_timer)
132 {
133 if (!m_timer.Enabled)
134 {
135 m_timer.Interval = m_Interval;
136 m_timer.Enabled = true;
137 m_timer.Start();
138 }
139 }
140 }
141
142 public void OnRegionHandleRequest(IClientAPI client, UUID regionID)
143 {
144 //m_log.DebugFormat("[SERVICE THROTTLE]: RegionHandleRequest {0}", regionID);
145 ulong handle = 0;
146 if (IsLocalRegionHandle(regionID, out handle))
147 {
148 client.SendRegionHandle(regionID, handle);
149 return;
150 }
151
152 Action action = delegate
153 {
154 GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, regionID);
155
156 if (r != null && r.RegionHandle != 0)
157 client.SendRegionHandle(regionID, r.RegionHandle);
158 };
159
160 Enqueue("region", regionID.ToString(), action);
161 }
162
163 #endregion Events
164
165 #region IServiceThrottleModule
166
167 public void Enqueue(string category, string itemid, Action continuation)
168 {
169 lock (m_RequestQueue)
170 {
171 if (m_Pending.ContainsKey(category))
172 {
173 if (m_Pending[category].Contains(itemid))
174 // Don't enqueue, it's already pending
175 return;
176 }
177 else
178 m_Pending.Add(category, new List<string>());
179
180 m_Pending[category].Add(itemid);
181
182 m_RequestQueue.Enqueue(delegate
183 {
184 lock (m_RequestQueue)
185 m_Pending[category].Remove(itemid);
186
187 continuation();
188 });
189 }
190 }
191
192 #endregion IServiceThrottleModule
193
194 #region Process Continuation Queue
195
196 private void ProcessQueue(object sender, System.Timers.ElapsedEventArgs e)
197 {
198 //m_log.DebugFormat("[YYY]: Process queue with {0} continuations", m_RequestQueue.Count);
199
200 while (m_RequestQueue.Count > 0)
201 {
202 Action continuation = null;
203 lock (m_RequestQueue)
204 continuation = m_RequestQueue.Dequeue();
205
206 if (continuation != null)
207 continuation();
208 }
209
210 if (AreThereRootAgents())
211 {
212 lock (m_timer)
213 {
214 m_timer.Interval = 1000; // 1 sec
215 m_timer.Enabled = true;
216 m_timer.Start();
217 }
218 }
219 else
220 lock (m_timer)
221 m_timer.Enabled = false;
222
223 }
224
225 #endregion Process Continuation Queue
226
227 #region Misc
228
229 private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle)
230 {
231 regionHandle = 0;
232 foreach (Scene s in m_scenes)
233 if (s.RegionInfo.RegionID == regionID)
234 {
235 regionHandle = s.RegionInfo.RegionHandle;
236 return true;
237 }
238 return false;
239 }
240
241 private bool AreThereRootAgents()
242 {
243 foreach (Scene s in m_scenes)
244 {
245 foreach (ScenePresence sp in s.GetScenePresences())
246 if (!sp.IsChildAgent)
247 return true;
248 }
249
250 return false;
251 }
252
253 #endregion Misc
254 }
255
256}
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
index 8ce20e9..245c808 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
@@ -54,11 +54,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
54 54
55 public new void Initialise(IConfigSource config) 55 public new void Initialise(IConfigSource config)
56 { 56 {
57 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name); 57 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", null);
58 if (umanmod == Name) 58 if (umanmod == Name)
59 { 59 {
60 m_Enabled = true; 60 m_Enabled = true;
61 RegisterConsoleCmds(); 61 Init();
62 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); 62 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name);
63 } 63 }
64 } 64 }
@@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
70 70
71 #endregion ISharedRegionModule 71 #endregion ISharedRegionModule
72 72
73 protected override void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users) 73 protected override void AddAdditionalUsers(string query, List<UserData> users)
74 { 74 {
75 if (query.Contains("@")) // First.Last@foo.com, maybe? 75 if (query.Contains("@")) // First.Last@foo.com, maybe?
76 { 76 {
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs
new file mode 100644
index 0000000..9d36aa5
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs
@@ -0,0 +1,76 @@
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 Nini.Config;
30using NUnit.Framework;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.CoreModules.Framework.UserManagement;
34using OpenSim.Tests.Common;
35using OpenSim.Tests.Common.Mock;
36
37namespace OpenSim.Region.CoreModules.Framework.UserManagement.Tests
38{
39 [TestFixture]
40 public class HGUserManagementModuleTests : OpenSimTestCase
41 {
42 /// <summary>
43 /// Test that a new HG agent (i.e. one without a user account) has their name cached in the UMM upon creation.
44 /// </summary>
45 [Test]
46 public void TestCachedUserNameForNewAgent()
47 {
48 TestHelpers.InMethod();
49// TestHelpers.EnableLogging();
50
51 HGUserManagementModule hgumm = new HGUserManagementModule();
52 UUID userId = TestHelpers.ParseStem("11");
53 string firstName = "Fred";
54 string lastName = "Astaire";
55 string homeUri = "example.com";
56
57 IConfigSource config = new IniConfigSource();
58 config.AddConfig("Modules");
59 config.Configs["Modules"].Set("UserManagementModule", hgumm.Name);
60
61 SceneHelpers sceneHelpers = new SceneHelpers();
62 TestScene scene = sceneHelpers.SetupScene();
63 SceneHelpers.SetupSceneModules(scene, config, hgumm);
64
65 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
66 acd.firstname = firstName;
67 acd.lastname = lastName;
68 acd.ServiceURLs["HomeURI"] = "http://" + homeUri;
69
70 SceneHelpers.AddScenePresence(scene, acd);
71
72 string name = hgumm.GetUserName(userId);
73 Assert.That(name, Is.EqualTo(string.Format("{0}.{1} @{2}", firstName, lastName, homeUri)));
74 }
75 }
76} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 77e8b00..3fb5195 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -28,9 +28,11 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.IO; 29using System.IO;
30using System.Reflection; 30using System.Reflection;
31using System.Threading;
31 32
32using OpenSim.Framework; 33using OpenSim.Framework;
33using OpenSim.Framework.Console; 34using OpenSim.Framework.Console;
35using OpenSim.Framework.Monitoring;
34using OpenSim.Region.ClientStack.LindenUDP; 36using OpenSim.Region.ClientStack.LindenUDP;
35using OpenSim.Region.Framework; 37using OpenSim.Region.Framework;
36using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
@@ -44,25 +46,19 @@ using log4net;
44using Nini.Config; 46using Nini.Config;
45using Mono.Addins; 47using Mono.Addins;
46 48
49using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
50
47namespace OpenSim.Region.CoreModules.Framework.UserManagement 51namespace OpenSim.Region.CoreModules.Framework.UserManagement
48{ 52{
49 public class UserData
50 {
51 public UUID Id { get; set; }
52 public string FirstName { get; set; }
53 public string LastName { get; set; }
54 public string HomeURL { get; set; }
55 public Dictionary<string, object> ServerURLs { get; set; }
56 }
57
58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")]
59 public class UserManagementModule : ISharedRegionModule, IUserManagement 54 public class UserManagementModule : ISharedRegionModule, IUserManagement, IPeople
60 { 55 {
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62 57
63 protected bool m_Enabled; 58 protected bool m_Enabled;
64 protected List<Scene> m_Scenes = new List<Scene>(); 59 protected List<Scene> m_Scenes = new List<Scene>();
65 60
61 protected IServiceThrottleModule m_ServiceThrottle;
66 // The cache 62 // The cache
67 protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>(); 63 protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>();
68 64
@@ -74,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
74 if (umanmod == Name) 70 if (umanmod == Name)
75 { 71 {
76 m_Enabled = true; 72 m_Enabled = true;
77 RegisterConsoleCmds(); 73 Init();
78 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); 74 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name);
79 } 75 }
80 } 76 }
@@ -101,6 +97,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
101 m_Scenes.Add(scene); 97 m_Scenes.Add(scene);
102 98
103 scene.RegisterModuleInterface<IUserManagement>(this); 99 scene.RegisterModuleInterface<IUserManagement>(this);
100 scene.RegisterModuleInterface<IPeople>(this);
104 scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); 101 scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
105 scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); 102 scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded);
106 } 103 }
@@ -117,6 +114,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
117 114
118 public void RegionLoaded(Scene s) 115 public void RegionLoaded(Scene s)
119 { 116 {
117 if (m_Enabled && m_ServiceThrottle == null)
118 m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
120 } 119 }
121 120
122 public void PostInitialise() 121 public void PostInitialise()
@@ -143,7 +142,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
143 s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); 142 s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
144 } 143 }
145 144
146
147 void EventManager_OnNewClient(IClientAPI client) 145 void EventManager_OnNewClient(IClientAPI client)
148 { 146 {
149 client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed); 147 client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed);
@@ -157,21 +155,43 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
157 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); 155 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest);
158 } 156 }
159 157
160 void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) 158 void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
161 { 159 {
160// m_log.DebugFormat(
161// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
162// uuid, remote_client.Name);
163
162 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) 164 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
163 { 165 {
164 remote_client.SendNameReply(uuid, "Mr", "OpenSim"); 166 client.SendNameReply(uuid, "Mr", "OpenSim");
165 } 167 }
166 else 168 else
167 { 169 {
168 string[] names = GetUserNames(uuid); 170 string[] names = new string[2];
169 if (names.Length == 2) 171 if (TryGetUserNamesFromCache(uuid, names))
170 { 172 {
171 //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); 173 client.SendNameReply(uuid, names[0], names[1]);
172 remote_client.SendNameReply(uuid, names[0], names[1]); 174 return;
173 } 175 }
174 176
177 // Not found in cache, queue continuation
178 m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate
179 {
180 //m_log.DebugFormat("[YYY]: Name request {0}", uuid);
181
182 // As least upto September 2013, clients permanently cache UUID -> Name bindings. Some clients
183 // appear to clear this when the user asks it to clear the cache, but others may not.
184 //
185 // So to avoid clients
186 // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will
187 // instead drop the request entirely.
188 if (TryGetUserNames(uuid, names))
189 client.SendNameReply(uuid, names[0], names[1]);
190// else
191// m_log.DebugFormat(
192// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}",
193// uuid, client.Name);
194 });
175 } 195 }
176 } 196 }
177 197
@@ -181,29 +201,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
181 201
182 m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); 202 m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query);
183 203
184 // searhc the user accounts service 204 List<UserData> users = GetUserData(query, 500, 1);
185 List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
186
187 List<UserData> users = new List<UserData>();
188 if (accs != null)
189 {
190 foreach (UserAccount acc in accs)
191 {
192 UserData ud = new UserData();
193 ud.FirstName = acc.FirstName;
194 ud.LastName = acc.LastName;
195 ud.Id = acc.PrincipalID;
196 users.Add(ud);
197 }
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
206 AddAdditionalUsers(avatarID, query, users);
207 205
208 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 206 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
209 // TODO: don't create new blocks if recycling an old packet 207 // TODO: don't create new blocks if recycling an old packet
@@ -249,12 +247,51 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
249 client.SendAvatarPickerReply(agent_data, data_args); 247 client.SendAvatarPickerReply(agent_data, data_args);
250 } 248 }
251 249
252 protected virtual void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users) 250 protected virtual void AddAdditionalUsers(string query, List<UserData> users)
253 { 251 {
254 } 252 }
255 253
256 #endregion Event Handlers 254 #endregion Event Handlers
257 255
256 #region IPeople
257
258 public List<UserData> GetUserData(string query, int page_size, int page_number)
259 {
260 // search the user accounts service
261 List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
262
263 List<UserData> users = new List<UserData>();
264 if (accs != null)
265 {
266 foreach (UserAccount acc in accs)
267 {
268 UserData ud = new UserData();
269 ud.FirstName = acc.FirstName;
270 ud.LastName = acc.LastName;
271 ud.Id = acc.PrincipalID;
272 users.Add(ud);
273 }
274 }
275
276 // search the local cache
277 lock (m_UserCache)
278 {
279 foreach (UserData data in m_UserCache.Values)
280 {
281 if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
282 (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower())))
283 users.Add(data);
284 }
285 }
286
287 AddAdditionalUsers(query, users);
288
289 return users;
290
291 }
292
293 #endregion IPeople
294
258 private void CacheCreators(SceneObjectGroup sog) 295 private void CacheCreators(SceneObjectGroup sog)
259 { 296 {
260 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification); 297 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification);
@@ -268,26 +305,56 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
268 } 305 }
269 } 306 }
270 307
271 private string[] GetUserNames(UUID uuid) 308 /// <summary>
309 ///
310 /// </summary>
311 /// <param name="uuid"></param>
312 /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
313 /// <returns></returns>
314 private bool TryGetUserNames(UUID uuid, string[] names)
272 { 315 {
273 string[] returnstring = new string[2]; 316 if (names == null)
317 names = new string[2];
318
319 if (TryGetUserNamesFromCache(uuid, names))
320 return true;
321
322 if (TryGetUserNamesFromServices(uuid, names))
323 return true;
324
325 return false;
326 }
274 327
328 private bool TryGetUserNamesFromCache(UUID uuid, string[] names)
329 {
275 lock (m_UserCache) 330 lock (m_UserCache)
276 { 331 {
277 if (m_UserCache.ContainsKey(uuid)) 332 if (m_UserCache.ContainsKey(uuid))
278 { 333 {
279 returnstring[0] = m_UserCache[uuid].FirstName; 334 names[0] = m_UserCache[uuid].FirstName;
280 returnstring[1] = m_UserCache[uuid].LastName; 335 names[1] = m_UserCache[uuid].LastName;
281 return returnstring; 336
337 return true;
282 } 338 }
283 } 339 }
284 340
341 return false;
342 }
343
344 /// <summary>
345 /// Try to get the names bound to the given uuid, from the services.
346 /// </summary>
347 /// <returns>True if the name was found, false if not.</returns>
348 /// <param name='uuid'></param>
349 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
350 private bool TryGetUserNamesFromServices(UUID uuid, string[] names)
351 {
285 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid); 352 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
286 353
287 if (account != null) 354 if (account != null)
288 { 355 {
289 returnstring[0] = account.FirstName; 356 names[0] = account.FirstName;
290 returnstring[1] = account.LastName; 357 names[1] = account.LastName;
291 358
292 UserData user = new UserData(); 359 UserData user = new UserData();
293 user.FirstName = account.FirstName; 360 user.FirstName = account.FirstName;
@@ -295,14 +362,42 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
295 362
296 lock (m_UserCache) 363 lock (m_UserCache)
297 m_UserCache[uuid] = user; 364 m_UserCache[uuid] = user;
365
366 return true;
298 } 367 }
299 else 368 else
300 { 369 {
301 returnstring[0] = "Unknown"; 370 // Let's try the GridUser service
302 returnstring[1] = "User"; 371 GridUserInfo uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString());
303 } 372 if (uInfo != null)
373 {
374 string url, first, last, tmp;
375 UUID u;
376 if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
377 {
378 AddUser(uuid, first, last, url);
379
380 if (m_UserCache.ContainsKey(uuid))
381 {
382 names[0] = m_UserCache[uuid].FirstName;
383 names[1] = m_UserCache[uuid].LastName;
384
385 return true;
386 }
387 }
388 else
389 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
390 }
391 else
392 {
393 m_log.DebugFormat("[USER MANAGEMENT MODULE]: No grid user found for {0}", uuid);
394 }
304 395
305 return returnstring; 396 names[0] = "Unknown";
397 names[1] = "UserUMMTGUN9";
398
399 return false;
400 }
306 } 401 }
307 402
308 #region IUserManagement 403 #region IUserManagement
@@ -338,16 +433,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
338 433
339 public string GetUserName(UUID uuid) 434 public string GetUserName(UUID uuid)
340 { 435 {
341 string[] names = GetUserNames(uuid); 436 string[] names = new string[2];
342 if (names.Length == 2) 437 TryGetUserNames(uuid, names);
343 {
344 string firstname = names[0];
345 string lastname = names[1];
346 438
347 return firstname + " " + lastname; 439 return names[0] + " " + names[1];
348 440
349 }
350 return "(hippos)";
351 } 441 }
352 442
353 public string GetUserHomeURL(UUID userID) 443 public string GetUserHomeURL(UUID userID)
@@ -376,7 +466,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
376 return userdata.ServerURLs[serverType].ToString(); 466 return userdata.ServerURLs[serverType].ToString();
377 } 467 }
378 468
379 if (userdata.HomeURL != null && userdata.HomeURL != string.Empty) 469 if (!string.IsNullOrEmpty(userdata.HomeURL))
380 { 470 {
381 //m_log.DebugFormat( 471 //m_log.DebugFormat(
382 // "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}", 472 // "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}",
@@ -394,14 +484,20 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
394 484
395 public string GetUserUUI(UUID userID) 485 public string GetUserUUI(UUID userID)
396 { 486 {
397 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID);
398 if (account != null)
399 return userID.ToString();
400
401 UserData ud; 487 UserData ud;
402 lock (m_UserCache) 488 lock (m_UserCache)
403 m_UserCache.TryGetValue(userID, out ud); 489 m_UserCache.TryGetValue(userID, out ud);
404 490
491 if (ud == null) // It's not in the cache
492 {
493 string[] names = new string[2];
494 // This will pull the data from either UserAccounts or GridUser
495 // and stick it into the cache
496 TryGetUserNamesFromServices(userID, names);
497 lock (m_UserCache)
498 m_UserCache.TryGetValue(userID, out ud);
499 }
500
405 if (ud != null) 501 if (ud != null)
406 { 502 {
407 string homeURL = ud.HomeURL; 503 string homeURL = ud.HomeURL;
@@ -446,77 +542,81 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
446 AddUser(uuid, homeURL + ";" + first + " " + last); 542 AddUser(uuid, homeURL + ";" + first + " " + last);
447 } 543 }
448 544
449 public void AddUser (UUID id, string creatorData) 545 public void AddUser(UUID id, string creatorData)
450 { 546 {
451 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData); 547 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
452 548
453 UserData oldUser; 549 UserData oldUser;
454 //lock the whole block - prevent concurrent update
455 lock (m_UserCache) 550 lock (m_UserCache)
551 m_UserCache.TryGetValue(id, out oldUser);
552
553 if (oldUser != null)
456 { 554 {
457 m_UserCache.TryGetValue (id, out oldUser); 555 if (string.IsNullOrEmpty(creatorData))
458 if (oldUser != null)
459 { 556 {
460 if (creatorData == null || creatorData == String.Empty) 557 //ignore updates without creator data
461 { 558 return;
462 //ignore updates without creator data
463 return;
464 }
465 //try update unknown users
466 //and creator's home URL's
467 if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL)))
468 {
469 m_UserCache.Remove (id);
470// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData,oldUser.HomeURL);
471 }
472 else
473 {
474 //we have already a valid user within the cache
475 return;
476 }
477 } 559 }
478 560
479 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount (m_Scenes [0].RegionInfo.ScopeID, id); 561 //try update unknown users, but don't update anyone else
480 562 if (oldUser.FirstName == "Unknown" && !creatorData.Contains("Unknown"))
481 if (account != null)
482 { 563 {
483 AddUser (id, account.FirstName, account.LastName); 564 lock (m_UserCache)
565 m_UserCache.Remove(id);
566 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData, oldUser.HomeURL);
484 } 567 }
485 else 568 else
486 { 569 {
487 UserData user = new UserData (); 570 //we have already a valid user within the cache
488 user.Id = id; 571 return;
572 }
573 }
489 574
490 if (creatorData != null && creatorData != string.Empty) 575 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, id);
491 {
492 //creatorData = <endpoint>;<name>
493 576
494 string[] parts = creatorData.Split (';'); 577 if (account != null)
495 if (parts.Length >= 1) 578 {
579 AddUser(id, account.FirstName, account.LastName);
580 }
581 else
582 {
583 UserData user = new UserData();
584 user.Id = id;
585
586 if (!string.IsNullOrEmpty(creatorData))
587 {
588 //creatorData = <endpoint>;<name>
589
590 string[] parts = creatorData.Split(';');
591 if (parts.Length >= 1)
592 {
593 user.HomeURL = parts[0];
594 try
496 { 595 {
497 user.HomeURL = parts [0]; 596 Uri uri = new Uri(parts[0]);
498 try 597 user.LastName = "@" + uri.Authority;
499 { 598 }
500 Uri uri = new Uri (parts [0]); 599 catch (UriFormatException)
501 user.LastName = "@" + uri.Authority; 600 {
502 } 601 m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]);
503 catch (UriFormatException) 602 user.LastName = "@unknown";
504 {
505 m_log.DebugFormat ("[SCENE]: Unable to parse Uri {0}", parts [0]);
506 user.LastName = "@unknown";
507 }
508 } 603 }
509 if (parts.Length >= 2)
510 user.FirstName = parts [1].Replace (' ', '.');
511 }
512 else
513 {
514 user.FirstName = "Unknown";
515 user.LastName = "User";
516 } 604 }
517 605
518 AddUserInternal (user); 606 if (parts.Length >= 2)
607 user.FirstName = parts[1].Replace(' ', '.');
608 }
609 else
610 {
611 // Temporarily add unknown user entries of this type into the cache so that we can distinguish
612 // this source from other recent (hopefully resolved) bugs that fail to retrieve a user name binding
613 // TODO: Can be removed when GUN* unknown users have definitely dropped significantly or
614 // disappeared.
615 user.FirstName = "Unknown";
616 user.LastName = "UserUMMAU4";
519 } 617 }
618
619 AddUserInternal(user);
520 } 620 }
521 } 621 }
522 622
@@ -541,9 +641,22 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
541 641
542 #endregion IUserManagement 642 #endregion IUserManagement
543 643
644 protected void Init()
645 {
646 AddUser(UUID.Zero, "Unknown", "User");
647 RegisterConsoleCmds();
648 }
649
544 protected void RegisterConsoleCmds() 650 protected void RegisterConsoleCmds()
545 { 651 {
546 MainConsole.Instance.Commands.AddCommand("Users", true, 652 MainConsole.Instance.Commands.AddCommand("Users", true,
653 "show name",
654 "show name <uuid>",
655 "Show the bindings between a single user UUID and a user name",
656 String.Empty,
657 HandleShowUser);
658
659 MainConsole.Instance.Commands.AddCommand("Users", true,
547 "show names", 660 "show names",
548 "show names", 661 "show names",
549 "Show the bindings between user UUIDs and user names", 662 "Show the bindings between user UUIDs and user names",
@@ -551,26 +664,56 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
551 HandleShowUsers); 664 HandleShowUsers);
552 } 665 }
553 666
554 private void HandleShowUsers(string module, string[] cmd) 667 private void HandleShowUser(string module, string[] cmd)
555 { 668 {
669 if (cmd.Length < 3)
670 {
671 MainConsole.Instance.OutputFormat("Usage: show name <uuid>");
672 return;
673 }
674
675 UUID userId;
676 if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId))
677 return;
678
679 string[] names;
680
681 UserData ud;
682
556 lock (m_UserCache) 683 lock (m_UserCache)
557 { 684 {
558 if (m_UserCache.Count == 0) 685 if (!m_UserCache.TryGetValue(userId, out ud))
559 { 686 {
560 MainConsole.Instance.Output("No users found"); 687 MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId);
561 return; 688 return;
562 } 689 }
563 690 }
564 MainConsole.Instance.Output("UUID User Name"); 691
565 MainConsole.Instance.Output("-----------------------------------------------------------------------------"); 692 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
693 cdt.AddColumn("UUID", 36);
694 cdt.AddColumn("Name", 30);
695 cdt.AddColumn("HomeURL", 40);
696 cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL);
697
698 MainConsole.Instance.Output(cdt.ToString());
699 }
700
701 private void HandleShowUsers(string module, string[] cmd)
702 {
703 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
704 cdt.AddColumn("UUID", 36);
705 cdt.AddColumn("Name", 30);
706 cdt.AddColumn("HomeURL", 40);
707
708 lock (m_UserCache)
709 {
566 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) 710 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
567 { 711 cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL);
568 MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})",
569 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL));
570 }
571
572 return;
573 } 712 }
713
714 MainConsole.Instance.Output(cdt.ToString());
574 } 715 }
716
575 } 717 }
718
576} \ No newline at end of file 719} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index 7b11658..8946b5c 100644
--- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
34using Mono.Addins; 35using Mono.Addins;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.CoreModules.World.WorldMap; 37using OpenSim.Region.CoreModules.World.WorldMap;
@@ -48,20 +49,63 @@ namespace OpenSim.Region.CoreModules.Hypergrid
48 // Remember the map area that each client has been exposed to in this region 49 // Remember the map area that each client has been exposed to in this region
49 private Dictionary<UUID, List<MapBlockData>> m_SeenMapBlocks = new Dictionary<UUID, List<MapBlockData>>(); 50 private Dictionary<UUID, List<MapBlockData>> m_SeenMapBlocks = new Dictionary<UUID, List<MapBlockData>>();
50 51
52 private string m_MapImageServerURL = string.Empty;
53
54 private IUserManagement m_UserManagement;
55
51 #region INonSharedRegionModule Members 56 #region INonSharedRegionModule Members
52 57
53 public override void Initialise(IConfigSource config) 58 public override void Initialise(IConfigSource source)
54 { 59 {
55 if (Util.GetConfigVarFromSections<string>( 60 if (Util.GetConfigVarFromSections<string>(
56 config, "WorldMapModule", new string[] { "Map", "Startup" }, "WorldMap") == "HGWorldMap") 61 source, "WorldMapModule", new string[] { "Map", "Startup" }, "WorldMap") == "HGWorldMap")
62 {
57 m_Enabled = true; 63 m_Enabled = true;
64
65 m_MapImageServerURL = Util.GetConfigVarFromSections<string>(source, "MapTileURL", new string[] {"LoginService", "HGWorldMap", "SimulatorFeatures"});
66
67 if (!string.IsNullOrEmpty(m_MapImageServerURL))
68 {
69 m_MapImageServerURL = m_MapImageServerURL.Trim();
70 if (!m_MapImageServerURL.EndsWith("/"))
71 m_MapImageServerURL = m_MapImageServerURL + "/";
72 }
73
74
75 }
58 } 76 }
59 77
60 public override void AddRegion(Scene scene) 78 public override void AddRegion(Scene scene)
61 { 79 {
80 if (!m_Enabled)
81 return;
82
62 base.AddRegion(scene); 83 base.AddRegion(scene);
63 84
64 scene.EventManager.OnClientClosed += new EventManager.ClientClosed(EventManager_OnClientClosed); 85 scene.EventManager.OnClientClosed += EventManager_OnClientClosed;
86 }
87
88 public override void RegionLoaded(Scene scene)
89 {
90 if (!m_Enabled)
91 return;
92
93 base.RegionLoaded(scene);
94 ISimulatorFeaturesModule featuresModule = m_scene.RequestModuleInterface<ISimulatorFeaturesModule>();
95
96 if (featuresModule != null)
97 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
98
99 m_UserManagement = m_scene.RequestModuleInterface<IUserManagement>();
100
101 }
102
103 public override void RemoveRegion(Scene scene)
104 {
105 if (!m_Enabled)
106 return;
107
108 scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
65 } 109 }
66 110
67 public override string Name 111 public override string Name
@@ -85,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Hypergrid
85 b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's 129 b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's
86 } 130 }
87 131
88 m_log.DebugFormat("[HG MAP]: Reseting {0} blocks", mapBlocks.Count); 132 m_log.DebugFormat("[HG MAP]: Resetting {0} blocks", mapBlocks.Count);
89 sp.ControllingClient.SendMapBlock(mapBlocks, 0); 133 sp.ControllingClient.SendMapBlock(mapBlocks, 0);
90 m_SeenMapBlocks.Remove(clientID); 134 m_SeenMapBlocks.Remove(clientID);
91 } 135 }
@@ -115,6 +159,20 @@ namespace OpenSim.Region.CoreModules.Hypergrid
115 return mapBlocks; 159 return mapBlocks;
116 } 160 }
117 161
162 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
163 {
164 if (m_UserManagement != null && !string.IsNullOrEmpty(m_MapImageServerURL) && !m_UserManagement.IsLocalGridUser(agentID))
165 {
166 OSD extras = new OSDMap();
167 if (features.ContainsKey("OpenSimExtras"))
168 extras = features["OpenSimExtras"];
169 else
170 features["OpenSimExtras"] = extras;
171
172 ((OSDMap)extras)["map-server-url"] = m_MapImageServerURL;
173
174 }
175 }
118 } 176 }
119 177
120 class MapArea 178 class MapArea
diff --git a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
index bfe0383..9809c86 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.6.*")] 33[assembly: AssemblyVersion("0.8.0.*")]
34 34
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/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 2b13a8b..5541063 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -412,7 +412,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
412 //public bool HttpVerboseThrottle = true; // not implemented 412 //public bool HttpVerboseThrottle = true; // not implemented
413 public List<string> HttpCustomHeaders = null; 413 public List<string> HttpCustomHeaders = null;
414 public bool HttpPragmaNoCache = true; 414 public bool HttpPragmaNoCache = true;
415 private Thread httpThread;
416 415
417 // Request info 416 // Request info
418 private UUID _itemID; 417 private UUID _itemID;
@@ -501,9 +500,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
501 Request.Headers.Add(HttpCustomHeaders[i], 500 Request.Headers.Add(HttpCustomHeaders[i],
502 HttpCustomHeaders[i+1]); 501 HttpCustomHeaders[i+1]);
503 } 502 }
504 if (proxyurl != null && proxyurl.Length > 0) 503 if (!string.IsNullOrEmpty(proxyurl))
505 { 504 {
506 if (proxyexcepts != null && proxyexcepts.Length > 0) 505 if (!string.IsNullOrEmpty(proxyexcepts))
507 { 506 {
508 string[] elist = proxyexcepts.Split(';'); 507 string[] elist = proxyexcepts.Split(';');
509 Request.Proxy = new WebProxy(proxyurl, true, elist); 508 Request.Proxy = new WebProxy(proxyurl, true, elist);
@@ -521,7 +520,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
521 Request.Headers[entry.Key] = entry.Value; 520 Request.Headers[entry.Key] = entry.Value;
522 521
523 // Encode outbound data 522 // Encode outbound data
524 if (OutboundBody.Length > 0) 523 if (!string.IsNullOrEmpty(OutboundBody))
525 { 524 {
526 byte[] data = Util.UTF8.GetBytes(OutboundBody); 525 byte[] data = Util.UTF8.GetBytes(OutboundBody);
527 526
@@ -622,7 +621,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
622 { 621 {
623 if (!WorkItem.Cancel()) 622 if (!WorkItem.Cancel())
624 { 623 {
625 WorkItem.Abort(); 624 WorkItem.Cancel(true);
626 } 625 }
627 } 626 }
628 catch (Exception) 627 catch (Exception)
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs
new file mode 100644
index 0000000..e812d81
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs
@@ -0,0 +1,198 @@
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.Net;
32using System.Reflection;
33using System.Runtime.Serialization;
34using System.Text;
35using System.Threading;
36using log4net.Config;
37using NUnit.Framework;
38using OpenMetaverse;
39using OpenMetaverse.Assets;
40using OpenSim.Framework;
41using OpenSim.Region.CoreModules.Scripting.HttpRequest;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Tests.Common;
44using OpenSim.Tests.Common.Mock;
45
46namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests
47{
48 class TestWebRequestCreate : IWebRequestCreate
49 {
50 public TestWebRequest NextRequest { get; set; }
51
52 public WebRequest Create(Uri uri)
53 {
54// NextRequest.RequestUri = uri;
55
56 return NextRequest;
57
58// return new TestWebRequest(new SerializationInfo(typeof(TestWebRequest), new FormatterConverter()), new StreamingContext());
59 }
60 }
61
62 class TestWebRequest : WebRequest
63 {
64 public override string ContentType { get; set; }
65 public override string Method { get; set; }
66
67 public Func<IAsyncResult, WebResponse> OnEndGetResponse { get; set; }
68
69 public TestWebRequest() : base()
70 {
71// Console.WriteLine("created");
72 }
73
74// public TestWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext)
75// : base(serializationInfo, streamingContext)
76// {
77// Console.WriteLine("created");
78// }
79
80 public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
81 {
82// Console.WriteLine("bish");
83 TestAsyncResult tasr = new TestAsyncResult();
84 callback(tasr);
85
86 return tasr;
87 }
88
89 public override WebResponse EndGetResponse(IAsyncResult asyncResult)
90 {
91// Console.WriteLine("bosh");
92 return OnEndGetResponse(asyncResult);
93 }
94 }
95
96 class TestHttpWebResponse : HttpWebResponse
97 {
98 public string Response { get; set; }
99
100 public TestHttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext)
101 : base(serializationInfo, streamingContext) {}
102
103 public override Stream GetResponseStream()
104 {
105 return new MemoryStream(Encoding.UTF8.GetBytes(Response));
106 }
107 }
108
109 class TestAsyncResult : IAsyncResult
110 {
111 WaitHandle m_wh = new ManualResetEvent(true);
112
113 object IAsyncResult.AsyncState
114 {
115 get {
116 throw new System.NotImplementedException ();
117 }
118 }
119
120 WaitHandle IAsyncResult.AsyncWaitHandle
121 {
122 get { return m_wh; }
123 }
124
125 bool IAsyncResult.CompletedSynchronously
126 {
127 get { return false; }
128 }
129
130 bool IAsyncResult.IsCompleted
131 {
132 get { return true; }
133 }
134 }
135
136 /// <summary>
137 /// Test script http request code.
138 /// </summary>
139 /// <remarks>
140 /// This class uses some very hacky workarounds in order to mock HttpWebResponse which are Mono dependent (though
141 /// alternative code can be written to make this work for Windows). However, the value of being able to
142 /// regression test this kind of code is very high.
143 /// </remarks>
144 [TestFixture]
145 public class ScriptsHttpRequestsTests : OpenSimTestCase
146 {
147 /// <summary>
148 /// Test what happens when we get a 404 response from a call.
149 /// </summary>
150 [Test]
151 public void Test404Response()
152 {
153 TestHelpers.InMethod();
154// TestHelpers.EnableLogging();
155
156 if (!Util.IsPlatformMono)
157 Assert.Ignore("Ignoring test since can only currently run on Mono");
158
159 string rawResponse = "boom";
160
161 TestWebRequestCreate twrc = new TestWebRequestCreate();
162
163 TestWebRequest twr = new TestWebRequest();
164 //twr.OnEndGetResponse += ar => new TestHttpWebResponse(null, new StreamingContext());
165 twr.OnEndGetResponse += ar =>
166 {
167 SerializationInfo si = new SerializationInfo(typeof(HttpWebResponse), new FormatterConverter());
168 StreamingContext sc = new StreamingContext();
169// WebHeaderCollection headers = new WebHeaderCollection();
170// si.AddValue("m_HttpResponseHeaders", headers);
171 si.AddValue("uri", new Uri("test://arrg"));
172// si.AddValue("m_Certificate", null);
173 si.AddValue("version", HttpVersion.Version11);
174 si.AddValue("statusCode", HttpStatusCode.NotFound);
175 si.AddValue("contentLength", 0);
176 si.AddValue("method", "GET");
177 si.AddValue("statusDescription", "Not Found");
178 si.AddValue("contentType", null);
179 si.AddValue("cookieCollection", new CookieCollection());
180
181 TestHttpWebResponse thwr = new TestHttpWebResponse(si, sc);
182 thwr.Response = rawResponse;
183
184 throw new WebException("no message", null, WebExceptionStatus.ProtocolError, thwr);
185 };
186
187 twrc.NextRequest = twr;
188
189 WebRequest.RegisterPrefix("test", twrc);
190 HttpRequestClass hr = new HttpRequestClass();
191 hr.Url = "test://something";
192 hr.SendRequest();
193
194 Assert.That(hr.Status, Is.EqualTo((int)HttpStatusCode.NotFound));
195 Assert.That(hr.ResponseBody, Is.EqualTo(rawResponse));
196 }
197 }
198} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 2a4d440..1983fed 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -219,7 +219,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
219 219
220 string uri = "/lslhttp/" + urlcode.ToString(); 220 string uri = "/lslhttp/" + urlcode.ToString();
221 221
222 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); 222 PollServiceEventArgs args
223 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
223 args.Type = PollServiceEventArgs.EventType.LslHttp; 224 args.Type = PollServiceEventArgs.EventType.LslHttp;
224 m_HttpServer.AddPollServiceHTTPHandler(uri, args); 225 m_HttpServer.AddPollServiceHTTPHandler(uri, args);
225 226
@@ -266,7 +267,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
266 267
267 string uri = "/lslhttps/" + urlcode.ToString(); 268 string uri = "/lslhttps/" + urlcode.ToString();
268 269
269 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); 270 PollServiceEventArgs args
271 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
270 args.Type = PollServiceEventArgs.EventType.LslHttp; 272 args.Type = PollServiceEventArgs.EventType.LslHttp;
271 m_HttpsServer.AddPollServiceHTTPHandler(uri, args); 273 m_HttpsServer.AddPollServiceHTTPHandler(uri, args);
272 274
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 65737fa..baf9f2f 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -161,9 +161,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
161 { 161 {
162 WebRequest request = HttpWebRequest.Create(url); 162 WebRequest request = HttpWebRequest.Create(url);
163 163
164 if (m_proxyurl != null && m_proxyurl.Length > 0) 164 if (!string.IsNullOrEmpty(m_proxyurl))
165 { 165 {
166 if (m_proxyexcepts != null && m_proxyexcepts.Length > 0) 166 if (!string.IsNullOrEmpty(m_proxyexcepts))
167 { 167 {
168 string[] elist = m_proxyexcepts.Split(';'); 168 string[] elist = m_proxyexcepts.Split(';');
169 request.Proxy = new WebProxy(m_proxyurl, true, elist); 169 request.Proxy = new WebProxy(m_proxyurl, true, elist);
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index fccf053..ad33f23 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -45,6 +45,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
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);
48 private static string LogHeader = "[MODULE COMMS]";
48 49
49 private Dictionary<string,object> m_constants = new Dictionary<string,object>(); 50 private Dictionary<string,object> m_constants = new Dictionary<string,object>();
50 51
@@ -148,7 +149,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); 149 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
149 if (mi == null) 150 if (mi == null)
150 { 151 {
151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); 152 m_log.WarnFormat("{0} Failed to register method {1}", LogHeader, meth);
152 return; 153 return;
153 } 154 }
154 155
@@ -163,9 +164,9 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
163 164
164 public void RegisterScriptInvocation(object target, MethodInfo mi) 165 public void RegisterScriptInvocation(object target, MethodInfo mi)
165 { 166 {
166 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); 167// m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
167 168
168 Type delegateType; 169 Type delegateType = typeof(void);
169 List<Type> typeArgs = mi.GetParameters() 170 List<Type> typeArgs = mi.GetParameters()
170 .Select(p => p.ParameterType) 171 .Select(p => p.ParameterType)
171 .ToList(); 172 .ToList();
@@ -176,8 +177,16 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
176 } 177 }
177 else 178 else
178 { 179 {
179 typeArgs.Add(mi.ReturnType); 180 try
180 delegateType = Expression.GetFuncType(typeArgs.ToArray()); 181 {
182 typeArgs.Add(mi.ReturnType);
183 delegateType = Expression.GetFuncType(typeArgs.ToArray());
184 }
185 catch (Exception e)
186 {
187 m_log.ErrorFormat("{0} Failed to create function signature. Most likely more than 5 parameters. Method={1}. Error={2}",
188 LogHeader, mi.Name, e);
189 }
181 } 190 }
182 191
183 Delegate fcall; 192 Delegate fcall;
@@ -325,7 +334,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
325 /// </summary> 334 /// </summary>
326 public void RegisterConstant(string cname, object value) 335 public void RegisterConstant(string cname, object value)
327 { 336 {
328 m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); 337// m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString());
329 lock (m_constants) 338 lock (m_constants)
330 { 339 {
331 m_constants.Add(cname,value); 340 m_constants.Add(cname,value);
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 41baccc..7119137 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -152,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
152 TestHelpers.InMethod(); 152 TestHelpers.InMethod();
153 153
154 string dtText 154 string dtText
155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; 155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://0.0.0.0/shouldnotexist.png";
156 156
157 SetupScene(false); 157 SetupScene(false);
158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); 158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
@@ -307,7 +307,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
307 TestHelpers.InMethod(); 307 TestHelpers.InMethod();
308 308
309 string dtText 309 string dtText
310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; 310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://0.0.0.0/shouldnotexist.png";
311 311
312 SetupScene(true); 312 SetupScene(true);
313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); 313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
index cbffca7..c6e05b1 100644
--- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
@@ -677,7 +677,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
677 // if not, use as method name 677 // if not, use as method name
678 UUID parseUID; 678 UUID parseUID;
679 string mName = "llRemoteData"; 679 string mName = "llRemoteData";
680 if ((Channel != null) && (Channel != "")) 680 if (!string.IsNullOrEmpty(Channel))
681 if (!UUID.TryParse(Channel, out parseUID)) 681 if (!UUID.TryParse(Channel, out parseUID))
682 mName = Channel; 682 mName = Channel;
683 else 683 else
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
new file mode 100644
index 0000000..323535a
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
@@ -0,0 +1,226 @@
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
29using log4net;
30using Mono.Addins;
31using Nini.Config;
32using System;
33using System.Collections.Generic;
34using System.Reflection;
35using OpenSim.Framework;
36using OpenSim.Framework.Console;
37using OpenSim.Server.Base;
38using OpenSim.Server.Handlers;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Framework.Servers;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Services.Interfaces;
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45using OpenMetaverse;
46
47namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile
48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalUserProfilesServicesConnector")]
50 public class LocalUserProfilesServicesConnector : ISharedRegionModule
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(
54 MethodBase.GetCurrentMethod().DeclaringType);
55
56 private Dictionary<UUID, Scene> regions = new Dictionary<UUID, Scene>();
57
58 public IUserProfilesService ServiceModule
59 {
60 get; private set;
61 }
62
63 public bool Enabled
64 {
65 get; private set;
66 }
67
68 public string Name
69 {
70 get
71 {
72 return "LocalUserProfilesServicesConnector";
73 }
74 }
75
76 public string ConfigName
77 {
78 get; private set;
79 }
80
81 public Type ReplaceableInterface
82 {
83 get { return null; }
84 }
85
86 public LocalUserProfilesServicesConnector()
87 {
88 m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector no params");
89 }
90
91 public LocalUserProfilesServicesConnector(IConfigSource source)
92 {
93 m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector instantiated directly.");
94 InitialiseService(source);
95 }
96
97 public void InitialiseService(IConfigSource source)
98 {
99 ConfigName = "UserProfilesService";
100
101 // Instantiate the request handler
102 IHttpServer Server = MainServer.Instance;
103
104 IConfig config = source.Configs[ConfigName];
105 if (config == null)
106 {
107 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: UserProfilesService missing from OpenSim.ini");
108 return;
109 }
110
111 if(!config.GetBoolean("Enabled",false))
112 {
113 Enabled = false;
114 return;
115 }
116
117 Enabled = true;
118
119 string serviceDll = config.GetString("LocalServiceModule",
120 String.Empty);
121
122 if (serviceDll == String.Empty)
123 {
124 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: No LocalServiceModule named in section UserProfilesService");
125 return;
126 }
127
128 Object[] args = new Object[] { source, ConfigName };
129 ServiceModule =
130 ServerUtils.LoadPlugin<IUserProfilesService>(serviceDll,
131 args);
132
133 if (ServiceModule == null)
134 {
135 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: Can't load user profiles service");
136 return;
137 }
138
139 Enabled = true;
140
141 JsonRpcProfileHandlers handler = new JsonRpcProfileHandlers(ServiceModule);
142
143 Server.AddJsonRPCHandler("avatarclassifiedsrequest", handler.AvatarClassifiedsRequest);
144 Server.AddJsonRPCHandler("classified_update", handler.ClassifiedUpdate);
145 Server.AddJsonRPCHandler("classifieds_info_query", handler.ClassifiedInfoRequest);
146 Server.AddJsonRPCHandler("classified_delete", handler.ClassifiedDelete);
147 Server.AddJsonRPCHandler("avatarpicksrequest", handler.AvatarPicksRequest);
148 Server.AddJsonRPCHandler("pickinforequest", handler.PickInfoRequest);
149 Server.AddJsonRPCHandler("picks_update", handler.PicksUpdate);
150 Server.AddJsonRPCHandler("picks_delete", handler.PicksDelete);
151 Server.AddJsonRPCHandler("avatarnotesrequest", handler.AvatarNotesRequest);
152 Server.AddJsonRPCHandler("avatar_notes_update", handler.NotesUpdate);
153 Server.AddJsonRPCHandler("avatar_properties_request", handler.AvatarPropertiesRequest);
154 Server.AddJsonRPCHandler("avatar_properties_update", handler.AvatarPropertiesUpdate);
155 Server.AddJsonRPCHandler("avatar_interests_update", handler.AvatarInterestsUpdate);
156 Server.AddJsonRPCHandler("image_assets_request", handler.AvatarImageAssetsRequest);
157 Server.AddJsonRPCHandler("user_data_request", handler.RequestUserAppData);
158 Server.AddJsonRPCHandler("user_data_update", handler.UpdateUserAppData);
159
160 }
161
162 #region ISharedRegionModule implementation
163
164 void ISharedRegionModule.PostInitialise()
165 {
166 if(!Enabled)
167 return;
168 }
169
170 #endregion
171
172 #region IRegionModuleBase implementation
173
174 void IRegionModuleBase.Initialise(IConfigSource source)
175 {
176 IConfig moduleConfig = source.Configs["Modules"];
177 if (moduleConfig != null)
178 {
179 string name = moduleConfig.GetString("UserProfilesServices", "");
180 if (name == Name)
181 {
182 InitialiseService(source);
183 m_log.Info("[LOCAL USERPROFILES SERVICE CONNECTOR]: Local user profiles connector enabled");
184 }
185 }
186 }
187
188 void IRegionModuleBase.Close()
189 {
190 return;
191 }
192
193 void IRegionModuleBase.AddRegion(Scene scene)
194 {
195 if (!Enabled)
196 return;
197
198 lock (regions)
199 {
200 if (regions.ContainsKey(scene.RegionInfo.RegionID))
201 m_log.ErrorFormat("[LOCAL USERPROFILES SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
202 else
203 regions.Add(scene.RegionInfo.RegionID, scene);
204 }
205 }
206
207 void IRegionModuleBase.RemoveRegion(Scene scene)
208 {
209 if (!Enabled)
210 return;
211
212 lock (regions)
213 {
214 if (regions.ContainsKey(scene.RegionInfo.RegionID))
215 regions.Remove(scene.RegionInfo.RegionID);
216 }
217 }
218
219 void IRegionModuleBase.RegionLoaded(Scene scene)
220 {
221 if (!Enabled)
222 return;
223 }
224 #endregion
225 }
226} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index d221d68..9f58175 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -322,7 +322,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
322 // a copy of the local asset. 322 // a copy of the local asset.
323 m_Cache.Cache(asset); 323 m_Cache.Cache(asset);
324 324
325 if (asset.Temporary || asset.Local) 325 if (asset.Local)
326 { 326 {
327 if (m_Cache != null) 327 if (m_Cache != null)
328 m_Cache.Cache(asset); 328 m_Cache.Cache(asset);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index 480cd69..52b1039 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -258,7 +258,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
258 if (m_Cache != null) 258 if (m_Cache != null)
259 m_Cache.Cache(asset); 259 m_Cache.Cache(asset);
260 260
261 if (asset.Temporary || asset.Local) 261 if (asset.Local)
262 { 262 {
263// m_log.DebugFormat( 263// m_log.DebugFormat(
264// "[LOCAL ASSET SERVICE CONNECTOR]: Returning asset {0} {1} without querying database since status Temporary = {2}, Local = {3}", 264// "[LOCAL ASSET SERVICE CONNECTOR]: Returning asset {0} {1} without querying database since status Temporary = {2}, Local = {3}",
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
index 1982473..4f75191 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
@@ -42,7 +42,7 @@ using OpenSim.Tests.Common;
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests 42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
43{ 43{
44 [TestFixture] 44 [TestFixture]
45 public class AssetConnectorsTests : OpenSimTestCase 45 public class AssetConnectorTests : OpenSimTestCase
46 { 46 {
47 [Test] 47 [Test]
48 public void TestAddAsset() 48 public void TestAddAsset()
@@ -77,7 +77,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
77 // TODO: Add cache and check that this does receive a copy of the asset 77 // TODO: Add cache and check that this does receive a copy of the asset
78 } 78 }
79 79
80 [Test]
81 public void TestAddTemporaryAsset() 80 public void TestAddTemporaryAsset()
82 { 81 {
83 TestHelpers.InMethod(); 82 TestHelpers.InMethod();
@@ -93,8 +92,45 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
93 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); 92 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
94 lasc.Initialise(config); 93 lasc.Initialise(config);
95 94
95 // If it is remote, it should be stored
96 AssetBase a2 = AssetHelpers.CreateNotecardAsset();
97 a2.Local = false;
98 a2.Temporary = true;
99
100 lasc.Store(a2);
101
102 AssetBase retreivedA2 = lasc.Get(a2.ID);
103 Assert.That(retreivedA2.ID, Is.EqualTo(a2.ID));
104 Assert.That(retreivedA2.Metadata.ID, Is.EqualTo(a2.Metadata.ID));
105 Assert.That(retreivedA2.Data.Length, Is.EqualTo(a2.Data.Length));
106
107 AssetMetadata retrievedA2Metadata = lasc.GetMetadata(a2.ID);
108 Assert.That(retrievedA2Metadata.ID, Is.EqualTo(a2.ID));
109
110 byte[] retrievedA2Data = lasc.GetData(a2.ID);
111 Assert.That(retrievedA2Data.Length, Is.EqualTo(a2.Data.Length));
112
113 // TODO: Add cache and check that this does receive a copy of the asset
114 }
115
116 [Test]
117 public void TestAddLocalAsset()
118 {
119 TestHelpers.InMethod();
120// TestHelpers.EnableLogging();
121
122 IConfigSource config = new IniConfigSource();
123 config.AddConfig("Modules");
124 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
125 config.AddConfig("AssetService");
126 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
127 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
128
129 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
130 lasc.Initialise(config);
131
96 AssetBase a1 = AssetHelpers.CreateNotecardAsset(); 132 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
97 a1.Temporary = true; 133 a1.Local = true;
98 134
99 lasc.Store(a1); 135 lasc.Store(a1);
100 136
@@ -106,7 +142,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
106 } 142 }
107 143
108 [Test] 144 [Test]
109 public void TestAddLocalAsset() 145 public void TestAddTemporaryLocalAsset()
110 { 146 {
111 TestHelpers.InMethod(); 147 TestHelpers.InMethod();
112// TestHelpers.EnableLogging(); 148// TestHelpers.EnableLogging();
@@ -121,8 +157,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
121 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); 157 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
122 lasc.Initialise(config); 158 lasc.Initialise(config);
123 159
160 // If it is local, it should not be stored
124 AssetBase a1 = AssetHelpers.CreateNotecardAsset(); 161 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
125 a1.Local = true; 162 a1.Local = true;
163 a1.Temporary = true;
126 164
127 lasc.Store(a1); 165 lasc.Store(a1);
128 166
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index c0c2ca7..31ef79b 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
56 56
57 public LocalGridServicesConnector() 57 public LocalGridServicesConnector()
58 { 58 {
59 m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector no parms.");
59 } 60 }
60 61
61 public LocalGridServicesConnector(IConfigSource source) 62 public LocalGridServicesConnector(IConfigSource source)
@@ -142,10 +143,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
142 143
143 scene.RegisterModuleInterface<IGridService>(this); 144 scene.RegisterModuleInterface<IGridService>(this);
144 145
145 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID)) 146 lock (m_LocalCache)
146 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!"); 147 {
147 else 148 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID))
148 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene)); 149 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
150 else
151 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene));
152 }
149 } 153 }
150 154
151 public void RemoveRegion(Scene scene) 155 public void RemoveRegion(Scene scene)
@@ -153,8 +157,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
153 if (!m_Enabled) 157 if (!m_Enabled)
154 return; 158 return;
155 159
156 m_LocalCache[scene.RegionInfo.RegionID].Clear(); 160 lock (m_LocalCache)
157 m_LocalCache.Remove(scene.RegionInfo.RegionID); 161 {
162 m_LocalCache[scene.RegionInfo.RegionID].Clear();
163 m_LocalCache.Remove(scene.RegionInfo.RegionID);
164 }
158 } 165 }
159 166
160 public void RegionLoaded(Scene scene) 167 public void RegionLoaded(Scene scene)
@@ -191,12 +198,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
191 198
192 // First see if it's a neighbour, even if it isn't on this sim. 199 // First see if it's a neighbour, even if it isn't on this sim.
193 // Neighbour data is cached in memory, so this is fast 200 // Neighbour data is cached in memory, so this is fast
194 foreach (RegionCache rcache in m_LocalCache.Values) 201
202 lock (m_LocalCache)
195 { 203 {
196 region = rcache.GetRegionByPosition(x, y); 204 foreach (RegionCache rcache in m_LocalCache.Values)
197 if (region != null)
198 { 205 {
199 return region; 206 region = rcache.GetRegionByPosition(x, y);
207 if (region != null)
208 {
209 return region;
210 }
200 } 211 }
201 } 212 }
202 213
@@ -224,6 +235,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
224 return m_GridService.GetDefaultRegions(scopeID); 235 return m_GridService.GetDefaultRegions(scopeID);
225 } 236 }
226 237
238 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
239 {
240 return m_GridService.GetDefaultHypergridRegions(scopeID);
241 }
242
227 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 243 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
228 { 244 {
229 return m_GridService.GetFallbackRegions(scopeID, x, y); 245 return m_GridService.GetFallbackRegions(scopeID, x, y);
@@ -245,12 +261,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
245 { 261 {
246 System.Text.StringBuilder caps = new System.Text.StringBuilder(); 262 System.Text.StringBuilder caps = new System.Text.StringBuilder();
247 263
248 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache) 264 lock (m_LocalCache)
249 { 265 {
250 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key); 266 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache)
251 List<GridRegion> regions = kvp.Value.GetNeighbours(); 267 {
252 foreach (GridRegion r in regions) 268 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key);
253 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize); 269 List<GridRegion> regions = kvp.Value.GetNeighbours();
270 foreach (GridRegion r in regions)
271 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize);
272 }
254 } 273 }
255 274
256 MainConsole.Instance.Output(caps.ToString()); 275 MainConsole.Instance.Output(caps.ToString());
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
index b2646ba..6a57d1f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
@@ -277,6 +277,26 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
277 return rinfo; 277 return rinfo;
278 } 278 }
279 279
280 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
281 {
282 List<GridRegion> rinfo = m_LocalGridService.GetDefaultHypergridRegions(scopeID);
283 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Local GetDefaultHypergridRegions {0} found {1} regions", name, rinfo.Count);
284 List<GridRegion> grinfo = m_RemoteGridService.GetDefaultHypergridRegions(scopeID);
285
286 if (grinfo != null)
287 {
288 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetDefaultHypergridRegions {0} found {1} regions", name, grinfo.Count);
289 foreach (GridRegion r in grinfo)
290 {
291 m_RegionInfoCache.Cache(r);
292 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null)
293 rinfo.Add(r);
294 }
295 }
296
297 return rinfo;
298 }
299
280 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 300 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
281 { 301 {
282 List<GridRegion> rinfo = m_LocalGridService.GetFallbackRegions(scopeID, x, y); 302 List<GridRegion> rinfo = m_LocalGridService.GetFallbackRegions(scopeID, x, y);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index 221f815..e05d186 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -81,6 +81,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
81 81
82 public void OnConnectionClose(IClientAPI client) 82 public void OnConnectionClose(IClientAPI client)
83 { 83 {
84 if (client == null)
85 return;
86 if (client.SceneAgent == null)
87 return;
88
84 if (client.SceneAgent.IsChildAgent) 89 if (client.SceneAgent.IsChildAgent)
85 return; 90 return;
86 91
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index e474ef6..77a3c82 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
@@ -233,6 +233,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
233 if (sp != null) 233 if (sp != null)
234 { 234 {
235 AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 235 AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
236 if (aCircuit == null)
237 return;
238 if (aCircuit.ServiceURLs == null)
239 return;
240
236 if (aCircuit.ServiceURLs.ContainsKey("InventoryServerURI")) 241 if (aCircuit.ServiceURLs.ContainsKey("InventoryServerURI"))
237 { 242 {
238 inventoryURL = aCircuit.ServiceURLs["InventoryServerURI"].ToString(); 243 inventoryURL = aCircuit.ServiceURLs["InventoryServerURI"].ToString();
@@ -254,7 +259,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
254 if (sp == null) 259 if (sp == null)
255 { 260 {
256 inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI"); 261 inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI");
257 if (inventoryURL != null && inventoryURL != string.Empty) 262 if (!string.IsNullOrEmpty(inventoryURL))
258 { 263 {
259 inventoryURL = inventoryURL.Trim(new char[] { '/' }); 264 inventoryURL = inventoryURL.Trim(new char[] { '/' });
260 m_InventoryURLs.Add(userID, inventoryURL); 265 m_InventoryURLs.Add(userID, inventoryURL);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
index 1e434b9..2fc8ee3 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
@@ -1,11 +1,41 @@
1using System; 1/*
2using System.Collections.Generic; 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 */
3 27
28using System;
29using System.Collections.Generic;
30using System.Threading;
4using OpenSim.Framework; 31using OpenSim.Framework;
5using OpenMetaverse; 32using OpenMetaverse;
6 33
7namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory 34namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
8{ 35{
36 /// <summary>
37 /// Cache root and system inventory folders to reduce number of potentially remote inventory calls and associated holdups.
38 /// </summary>
9 public class InventoryCache 39 public class InventoryCache
10 { 40 {
11 private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour 41 private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour
@@ -16,8 +46,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
16 46
17 public void Cache(UUID userID, InventoryFolderBase root) 47 public void Cache(UUID userID, InventoryFolderBase root)
18 { 48 {
19 lock (m_RootFolders) 49 m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS);
20 m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS);
21 } 50 }
22 51
23 public InventoryFolderBase GetRootFolder(UUID userID) 52 public InventoryFolderBase GetRootFolder(UUID userID)
@@ -31,14 +60,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
31 60
32 public void Cache(UUID userID, AssetType type, InventoryFolderBase folder) 61 public void Cache(UUID userID, AssetType type, InventoryFolderBase folder)
33 { 62 {
34 lock (m_FolderTypes) 63 Dictionary<AssetType, InventoryFolderBase> ff = null;
64 if (!m_FolderTypes.TryGetValue(userID, out ff))
65 {
66 ff = new Dictionary<AssetType, InventoryFolderBase>();
67 m_FolderTypes.Add(userID, ff, CACHE_EXPIRATION_SECONDS);
68 }
69
70 // We need to lock here since two threads could potentially retrieve the same dictionary
71 // and try to add a folder for that type simultaneously. Dictionary<>.Add() is not described as thread-safe in the SDK
72 // even if the folders are identical.
73 lock (ff)
35 { 74 {
36 Dictionary<AssetType, InventoryFolderBase> ff = null;
37 if (!m_FolderTypes.TryGetValue(userID, out ff))
38 {
39 ff = new Dictionary<AssetType, InventoryFolderBase>();
40 m_FolderTypes.Add(userID, ff, CACHE_EXPIRATION_SECONDS);
41 }
42 if (!ff.ContainsKey(type)) 75 if (!ff.ContainsKey(type))
43 ff.Add(type, folder); 76 ff.Add(type, folder);
44 } 77 }
@@ -50,8 +83,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
50 if (m_FolderTypes.TryGetValue(userID, out ff)) 83 if (m_FolderTypes.TryGetValue(userID, out ff))
51 { 84 {
52 InventoryFolderBase f = null; 85 InventoryFolderBase f = null;
53 if (ff.TryGetValue(type, out f)) 86
54 return f; 87 lock (ff)
88 {
89 if (ff.TryGetValue(type, out f))
90 return f;
91 }
55 } 92 }
56 93
57 return null; 94 return null;
@@ -59,8 +96,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
59 96
60 public void Cache(UUID userID, InventoryCollection inv) 97 public void Cache(UUID userID, InventoryCollection inv)
61 { 98 {
62 lock (m_Inventories) 99 m_Inventories.AddOrUpdate(userID, inv, 120);
63 m_Inventories.AddOrUpdate(userID, inv, 120);
64 } 100 }
65 101
66 public InventoryCollection GetUserInventory(UUID userID) 102 public InventoryCollection GetUserInventory(UUID userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index ec5751d..99913a9 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
@@ -196,7 +196,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
196 Util.FireAndForget(delegate 196 Util.FireAndForget(delegate
197 { 197 {
198 foreach (InventoryItemBase item in items) 198 foreach (InventoryItemBase item in items)
199 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 199 if (!string.IsNullOrEmpty(item.CreatorData))
200 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
200 }); 201 });
201 } 202 }
202 203
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index 2d3ba82..7f78076 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -195,18 +195,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
195 { 195 {
196 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); 196 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID);
197 197
198 if (invCol != null && UserManager != null) 198 // Commenting this for now, because it's causing more grief than good
199 { 199 //if (invCol != null && UserManager != null)
200 // Protect ourselves against the caller subsequently modifying the items list 200 //{
201 List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items); 201 // // Protect ourselves against the caller subsequently modifying the items list
202 202 // List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items);
203 if (items != null && items.Count > 0) 203
204 Util.FireAndForget(delegate 204 // if (items != null && items.Count > 0)
205 { 205 // //Util.FireAndForget(delegate
206 foreach (InventoryItemBase item in items) 206 // //{
207 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 207 // foreach (InventoryItemBase item in items)
208 }); 208 // if (!string.IsNullOrEmpty(item.CreatorData))
209 } 209 // UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
210 // //});
211 //}
210 212
211 return invCol; 213 return invCol;
212 } 214 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
index 172bea1..516ad40 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
@@ -79,7 +79,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
79 79
80 public void OnConnectionClose(IClientAPI client) 80 public void OnConnectionClose(IClientAPI client)
81 { 81 {
82 if (!client.SceneAgent.IsChildAgent) 82 if (client != null && client.SceneAgent != null && !client.SceneAgent.IsChildAgent)
83 { 83 {
84// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); 84// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
85 m_PresenceService.LogoutAgent(client.SessionId); 85 m_PresenceService.LogoutAgent(client.SessionId);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 8b8bb37..7a6a174 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -46,9 +46,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 /// <summary> 48 /// <summary>
49 /// Version of this service 49 /// Version of this service.
50 /// </summary> 50 /// </summary>
51 private const string m_Version = "SIMULATION/0.1"; 51 /// <remarks>
52 /// Currently valid versions are "SIMULATION/0.1" and "SIMULATION/0.2"
53 /// </remarks>
54 public string ServiceVersion { get; set; }
52 55
53 /// <summary> 56 /// <summary>
54 /// Map region ID to scene. 57 /// Map region ID to scene.
@@ -62,28 +65,39 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
62 65
63 #region Region Module interface 66 #region Region Module interface
64 67
65 public void Initialise(IConfigSource config) 68 public void Initialise(IConfigSource configSource)
66 { 69 {
67 IConfig moduleConfig = config.Configs["Modules"]; 70 IConfig moduleConfig = configSource.Configs["Modules"];
68 if (moduleConfig != null) 71 if (moduleConfig != null)
69 { 72 {
70 string name = moduleConfig.GetString("SimulationServices", ""); 73 string name = moduleConfig.GetString("SimulationServices", "");
71 if (name == Name) 74 if (name == Name)
72 { 75 {
73 //IConfig userConfig = config.Configs["SimulationService"]; 76 InitialiseService(configSource);
74 //if (userConfig == null)
75 //{
76 // m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini");
77 // return;
78 //}
79 77
80 m_ModuleEnabled = true; 78 m_ModuleEnabled = true;
81 79
82 m_log.Info("[SIMULATION CONNECTOR]: Local simulation enabled"); 80 m_log.Info("[LOCAL SIMULATION CONNECTOR]: Local simulation enabled.");
83 } 81 }
84 } 82 }
85 } 83 }
86 84
85 public void InitialiseService(IConfigSource configSource)
86 {
87 ServiceVersion = "SIMULATION/0.2";
88 IConfig config = configSource.Configs["SimulationService"];
89 if (config != null)
90 {
91 ServiceVersion = config.GetString("ConnectorProtocolVersion", ServiceVersion);
92
93 if (ServiceVersion != "SIMULATION/0.1" && ServiceVersion != "SIMULATION/0.2")
94 throw new Exception(string.Format("Invalid ConnectorProtocolVersion {0}", ServiceVersion));
95
96 m_log.InfoFormat(
97 "[LOCAL SIMULATION CONNECTOR]: Initialized with connector protocol version {0}", ServiceVersion);
98 }
99 }
100
87 public void PostInitialise() 101 public void PostInitialise()
88 { 102 {
89 } 103 }
@@ -160,7 +174,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
160 174
161 #endregion 175 #endregion
162 176
163 #region ISimulation 177 #region ISimulationService
164 178
165 public IScene GetScene(UUID regionId) 179 public IScene GetScene(UUID regionId)
166 { 180 {
@@ -221,7 +235,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
221// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", 235// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
222// destination.RegionName, destination.RegionID); 236// destination.RegionName, destination.RegionID);
223 237
224 return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData); 238 return m_scenes[destination.RegionID].IncomingUpdateChildAgent(cAgentData);
225 } 239 }
226 240
227// m_log.DebugFormat( 241// m_log.DebugFormat(
@@ -231,7 +245,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
231 return false; 245 return false;
232 } 246 }
233 247
234 public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData) 248 public bool UpdateAgent(GridRegion destination, AgentPosition agentPosition)
235 { 249 {
236 if (destination == null) 250 if (destination == null)
237 return false; 251 return false;
@@ -243,37 +257,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
243 foreach (Scene s in m_scenes.Values) 257 foreach (Scene s in m_scenes.Values)
244 { 258 {
245// m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); 259// m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
246 s.IncomingChildAgentDataUpdate(cAgentData); 260 s.IncomingUpdateChildAgent(agentPosition);
247 } 261 }
248 262
249 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate"); 263 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
250 return true; 264 return true;
251 } 265 }
252 266
253 public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
254 {
255 agent = null;
256
257 if (destination == null)
258 return false;
259
260 if (m_scenes.ContainsKey(destination.RegionID))
261 {
262// m_log.DebugFormat(
263// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
264// s.RegionInfo.RegionName, destination.RegionHandle);
265
266 return m_scenes[destination.RegionID].IncomingRetrieveRootAgent(id, out agent);
267 }
268
269 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
270 return false;
271 }
272
273 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) 267 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
274 { 268 {
275 reason = "Communications failure"; 269 reason = "Communications failure";
276 version = m_Version; 270 version = ServiceVersion;
277 if (destination == null) 271 if (destination == null)
278 return false; 272 return false;
279 273
@@ -306,12 +300,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
306 return false; 300 return false;
307 } 301 }
308 302
309 public bool CloseChildAgent(GridRegion destination, UUID id) 303 public bool CloseAgent(GridRegion destination, UUID id, string auth_token)
310 {
311 return CloseAgent(destination, id);
312 }
313
314 public bool CloseAgent(GridRegion destination, UUID id)
315 { 304 {
316 if (destination == null) 305 if (destination == null)
317 return false; 306 return false;
@@ -322,7 +311,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
322// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", 311// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
323// s.RegionInfo.RegionName, destination.RegionHandle); 312// s.RegionInfo.RegionName, destination.RegionHandle);
324 313
325 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); }); 314 m_scenes[destination.RegionID].CloseAgent(id, false, auth_token);
326 return true; 315 return true;
327 } 316 }
328 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 317 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
@@ -363,7 +352,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
363 return false; 352 return false;
364 } 353 }
365 354
366 #endregion /* IInterregionComms */ 355 #endregion
367 356
368 #region Misc 357 #region Misc
369 358
@@ -383,4 +372,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
383 372
384 #endregion 373 #endregion
385 } 374 }
386} 375} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index c8698ca..ab912ed 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -50,9 +50,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")] 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")]
51 public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService 51 public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService
52 { 52 {
53 private bool initialized = false;
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 54
55 private bool initialized = false;
56 protected bool m_enabled = false; 56 protected bool m_enabled = false;
57 protected Scene m_aScene; 57 protected Scene m_aScene;
58 // RemoteSimulationConnector does not care about local regions; it delegates that to the Local module 58 // RemoteSimulationConnector does not care about local regions; it delegates that to the Local module
@@ -64,27 +64,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
64 64
65 #region Region Module interface 65 #region Region Module interface
66 66
67 public virtual void Initialise(IConfigSource config) 67 public virtual void Initialise(IConfigSource configSource)
68 { 68 {
69 69 IConfig moduleConfig = configSource.Configs["Modules"];
70 IConfig moduleConfig = config.Configs["Modules"];
71 if (moduleConfig != null) 70 if (moduleConfig != null)
72 { 71 {
73 string name = moduleConfig.GetString("SimulationServices", ""); 72 string name = moduleConfig.GetString("SimulationServices", "");
74 if (name == Name) 73 if (name == Name)
75 { 74 {
76 //IConfig userConfig = config.Configs["SimulationService"]; 75 m_localBackend = new LocalSimulationConnectorModule();
77 //if (userConfig == null) 76
78 //{ 77 m_localBackend.InitialiseService(configSource);
79 // m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini");
80 // return;
81 //}
82 78
83 m_remoteConnector = new SimulationServiceConnector(); 79 m_remoteConnector = new SimulationServiceConnector();
84 80
85 m_enabled = true; 81 m_enabled = true;
86 82
87 m_log.Info("[SIMULATION CONNECTOR]: Remote simulation enabled"); 83 m_log.Info("[REMOTE SIMULATION CONNECTOR]: Remote simulation enabled.");
88 } 84 }
89 } 85 }
90 } 86 }
@@ -142,8 +138,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
142 } 138 }
143 139
144 protected virtual void InitOnce(Scene scene) 140 protected virtual void InitOnce(Scene scene)
145 { 141 {
146 m_localBackend = new LocalSimulationConnectorModule();
147 m_aScene = scene; 142 m_aScene = scene;
148 //m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService); 143 //m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService);
149 m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName); 144 m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName);
@@ -151,7 +146,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
151 146
152 #endregion 147 #endregion
153 148
154 #region IInterregionComms 149 #region ISimulationService
155 150
156 public IScene GetScene(UUID regionId) 151 public IScene GetScene(UUID regionId)
157 { 152 {
@@ -194,7 +189,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
194 return false; 189 return false;
195 190
196 // Try local first 191 // Try local first
197 if (m_localBackend.IsLocalRegion(destination.RegionHandle)) 192 if (m_localBackend.IsLocalRegion(destination.RegionID))
198 return m_localBackend.UpdateAgent(destination, cAgentData); 193 return m_localBackend.UpdateAgent(destination, cAgentData);
199 194
200 return m_remoteConnector.UpdateAgent(destination, cAgentData); 195 return m_remoteConnector.UpdateAgent(destination, cAgentData);
@@ -206,30 +201,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
206 return false; 201 return false;
207 202
208 // Try local first 203 // Try local first
209 if (m_localBackend.IsLocalRegion(destination.RegionHandle)) 204 if (m_localBackend.IsLocalRegion(destination.RegionID))
210 return m_localBackend.UpdateAgent(destination, cAgentData); 205 return m_localBackend.UpdateAgent(destination, cAgentData);
211 206
212 return m_remoteConnector.UpdateAgent(destination, cAgentData); 207 return m_remoteConnector.UpdateAgent(destination, cAgentData);
213 } 208 }
214 209
215 public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
216 {
217 agent = null;
218
219 if (destination == null)
220 return false;
221
222 // Try local first
223 if (m_localBackend.RetrieveAgent(destination, id, out agent))
224 return true;
225
226 // else do the remote thing
227 if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
228 return m_remoteConnector.RetrieveAgent(destination, id, out agent);
229
230 return false;
231 }
232
233 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) 210 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
234 { 211 {
235 reason = "Communications failure"; 212 reason = "Communications failure";
@@ -262,34 +239,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
262 return false; 239 return false;
263 } 240 }
264 241
265 public bool CloseChildAgent(GridRegion destination, UUID id) 242 public bool CloseAgent(GridRegion destination, UUID id, string auth_token)
266 {
267 if (destination == null)
268 return false;
269
270 // Try local first
271 if (m_localBackend.CloseChildAgent(destination, id))
272 return true;
273
274 // else do the remote thing
275 if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
276 return m_remoteConnector.CloseChildAgent(destination, id);
277
278 return false;
279 }
280
281 public bool CloseAgent(GridRegion destination, UUID id)
282 { 243 {
283 if (destination == null) 244 if (destination == null)
284 return false; 245 return false;
285 246
286 // Try local first 247 // Try local first
287 if (m_localBackend.CloseAgent(destination, id)) 248 if (m_localBackend.CloseAgent(destination, id, auth_token))
288 return true; 249 return true;
289 250
290 // else do the remote thing 251 // else do the remote thing
291 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 252 if (!m_localBackend.IsLocalRegion(destination.RegionID))
292 return m_remoteConnector.CloseAgent(destination, id); 253 return m_remoteConnector.CloseAgent(destination, id, auth_token);
293 254
294 return false; 255 return false;
295 } 256 }
@@ -311,12 +272,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
311 } 272 }
312 273
313 // else do the remote thing 274 // else do the remote thing
314 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 275 if (!m_localBackend.IsLocalRegion(destination.RegionID))
315 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall); 276 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall);
316 277
317 return false; 278 return false;
318 } 279 }
319 280
320 #endregion /* IInterregionComms */ 281 #endregion
321 } 282 }
322} 283}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index fcfdf7c..efc4998 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -464,7 +464,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
464 // or creator data is present. Otherwise, use the estate owner instead. 464 // or creator data is present. Otherwise, use the estate owner instead.
465 foreach (SceneObjectPart part in sceneObject.Parts) 465 foreach (SceneObjectPart part in sceneObject.Parts)
466 { 466 {
467 if (part.CreatorData == null || part.CreatorData == string.Empty) 467 if (string.IsNullOrEmpty(part.CreatorData))
468 { 468 {
469 if (!ResolveUserUuid(scene, part.CreatorID)) 469 if (!ResolveUserUuid(scene, part.CreatorID))
470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
@@ -515,7 +515,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
515 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 515 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
516 } 516 }
517 517
518 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) 518 if (string.IsNullOrEmpty(kvp.Value.CreatorData))
519 { 519 {
520 if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) 520 if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
521 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 521 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index a990898..7a844f4 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -178,7 +178,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
178 178
179 // Archive the regions 179 // Archive the regions
180 180
181 Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); 181 Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>();
182 182
183 scenesGroup.ForEachScene(delegate(Scene scene) 183 scenesGroup.ForEachScene(delegate(Scene scene)
184 { 184 {
@@ -216,7 +216,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
216 } 216 }
217 } 217 }
218 218
219 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) 219 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids)
220 { 220 {
221 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); 221 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
222 222
@@ -276,16 +276,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
276 RegionSettings regionSettings = scene.RegionInfo.RegionSettings; 276 RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
277 277
278 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) 278 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
279 assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; 279 assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture;
280 280
281 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) 281 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
282 assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; 282 assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture;
283 283
284 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) 284 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
285 assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; 285 assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture;
286 286
287 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) 287 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
288 assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; 288 assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture;
289 289
290 Save(scene, sceneObjects, regionDir); 290 Save(scene, sceneObjects, regionDir);
291 } 291 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index ada7ecc..6c2a631 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
81 /// <value> 81 /// <value>
82 /// uuids to request 82 /// uuids to request
83 /// </value> 83 /// </value>
84 protected IDictionary<UUID, AssetType> m_uuids; 84 protected IDictionary<UUID, sbyte> m_uuids;
85 85
86 /// <value> 86 /// <value>
87 /// Callback used when all the assets requested have been received. 87 /// Callback used when all the assets requested have been received.
@@ -115,7 +115,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
115 protected Dictionary<string, object> m_options; 115 protected Dictionary<string, object> m_options;
116 116
117 protected internal AssetsRequest( 117 protected internal AssetsRequest(
118 AssetsArchiver assetsArchiver, IDictionary<UUID, AssetType> uuids, 118 AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
119 IAssetService assetService, IUserAccountService userService, 119 IAssetService assetService, IUserAccountService userService,
120 UUID scope, Dictionary<string, object> options, 120 UUID scope, Dictionary<string, object> options,
121 AssetsRequestCallback assetsRequestCallback) 121 AssetsRequestCallback assetsRequestCallback)
@@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
154 154
155 m_requestCallbackTimer.Enabled = true; 155 m_requestCallbackTimer.Enabled = true;
156 156
157 foreach (KeyValuePair<UUID, AssetType> kvp in m_uuids) 157 foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids)
158 { 158 {
159// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); 159// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key);
160 160
@@ -235,9 +235,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
235 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer 235 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
236 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown) 236 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
237 { 237 {
238 AssetType type = (AssetType)assetType; 238 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
239 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, type); 239 fetchedAsset.Type = (sbyte)assetType;
240 fetchedAsset.Type = (sbyte)type;
241 } 240 }
242 241
243 AssetRequestCallback(fetchedAssetID, this, fetchedAsset); 242 AssetRequestCallback(fetchedAssetID, this, fetchedAsset);
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
index 4d49794..1659493 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
@@ -60,7 +60,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
60 60
61 public void Initialise() 61 public void Initialise()
62 { 62 {
63 m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName); 63// m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName);
64 64
65 m_module.Scene.AddCommand("Regions", m_module, "set terrain texture", 65 m_module.Scene.AddCommand("Regions", m_module, "set terrain texture",
66 "set terrain texture <number> <uuid> [<x>] [<y>]", 66 "set terrain texture <number> <uuid> [<x>] [<y>]",
@@ -76,6 +76,13 @@ namespace OpenSim.Region.CoreModules.World.Estate
76 " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.", 76 " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.",
77 consoleSetTerrainHeights); 77 consoleSetTerrainHeights);
78 78
79 m_module.Scene.AddCommand("Regions", m_module, "set water height",
80 "set water height <height> [<x>] [<y>]",
81 "Sets the water height in meters. If <x> and <y> are specified, it will only set it on regions with a matching coordinate. " +
82 "Specify -1 in <x> or <y> to wildcard that coordinate.",
83 consoleSetWaterHeight);
84
85
79 m_module.Scene.AddCommand( 86 m_module.Scene.AddCommand(
80 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand); 87 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand);
81 } 88 }
@@ -121,7 +128,29 @@ namespace OpenSim.Region.CoreModules.World.Estate
121 } 128 }
122 } 129 }
123 } 130 }
124 131 protected void consoleSetWaterHeight(string module, string[] args)
132 {
133 string heightstring = args[3];
134
135 int x = (args.Length > 4 ? int.Parse(args[4]) : -1);
136 int y = (args.Length > 5 ? int.Parse(args[5]) : -1);
137
138 if (x == -1 || m_module.Scene.RegionInfo.RegionLocX == x)
139 {
140 if (y == -1 || m_module.Scene.RegionInfo.RegionLocY == y)
141 {
142 double selectedheight = double.Parse(heightstring);
143
144 m_log.Debug("[ESTATEMODULE]: Setting water height in " + m_module.Scene.RegionInfo.RegionName + " to " +
145 string.Format(" {0}", selectedheight));
146 m_module.Scene.RegionInfo.RegionSettings.WaterHeight = selectedheight;
147
148 m_module.Scene.RegionInfo.RegionSettings.Save();
149 m_module.TriggerRegionInfoChange();
150 m_module.sendRegionHandshakeToAll();
151 }
152 }
153 }
125 protected void consoleSetTerrainHeights(string module, string[] args) 154 protected void consoleSetTerrainHeights(string module, string[] args)
126 { 155 {
127 string num = args[3]; 156 string num = args[3];
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 834fd77..47390e7 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -576,7 +576,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
576 if (!Scene.TeleportClientHome(user, s.ControllingClient)) 576 if (!Scene.TeleportClientHome(user, s.ControllingClient))
577 { 577 {
578 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out."); 578 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out.");
579 s.ControllingClient.Close(); 579 Scene.CloseAgent(s.UUID, false);
580 } 580 }
581 } 581 }
582 } 582 }
@@ -716,7 +716,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
716 } 716 }
717 } 717 }
718 718
719 public void handleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) 719 public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
720 { 720 {
721 SceneObjectPart part; 721 SceneObjectPart part;
722 722
@@ -756,7 +756,9 @@ namespace OpenSim.Region.CoreModules.World.Estate
756 default: 756 default:
757 break; 757 break;
758 } 758 }
759 SendTelehubInfo(client); 759
760 if (client != null)
761 SendTelehubInfo(client);
760 } 762 }
761 763
762 private void SendSimulatorBlueBoxMessage( 764 private void SendSimulatorBlueBoxMessage(
@@ -811,7 +813,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
811 if (!Scene.TeleportClientHome(prey, s.ControllingClient)) 813 if (!Scene.TeleportClientHome(prey, s.ControllingClient))
812 { 814 {
813 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 815 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
814 s.ControllingClient.Close(); 816 Scene.CloseAgent(s.UUID, false);
815 } 817 }
816 } 818 }
817 } 819 }
@@ -834,7 +836,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
834 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient)) 836 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient))
835 { 837 {
836 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 838 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
837 p.ControllingClient.Close(); 839 Scene.CloseAgent(p.UUID, false);
838 } 840 }
839 } 841 }
840 } 842 }
@@ -843,26 +845,23 @@ namespace OpenSim.Region.CoreModules.World.Estate
843 845
844 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID) 846 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID)
845 { 847 {
846 if (TerrainUploader != null) 848 lock (this)
847 { 849 {
848 lock (TerrainUploader) 850 if ((TerrainUploader != null) && (XferID == TerrainUploader.XferID))
849 { 851 {
850 if (XferID == TerrainUploader.XferID) 852 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
851 { 853 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
852 remoteClient.OnXferReceive -= TerrainUploader.XferReceive; 854 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
853 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
854 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
855 855
856 TerrainUploader = null; 856 TerrainUploader = null;
857 remoteClient.SendAlertMessage("Terrain Upload aborted by the client"); 857 remoteClient.SendAlertMessage("Terrain Upload aborted by the client");
858 }
859 } 858 }
860 } 859 }
861
862 } 860 }
861
863 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient) 862 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient)
864 { 863 {
865 lock (TerrainUploader) 864 lock (this)
866 { 865 {
867 remoteClient.OnXferReceive -= TerrainUploader.XferReceive; 866 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
868 remoteClient.OnAbortXfer -= AbortTerrainXferHandler; 867 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
@@ -921,22 +920,32 @@ namespace OpenSim.Region.CoreModules.World.Estate
921 920
922 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName) 921 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName)
923 { 922 {
924 if (TerrainUploader == null) 923 lock (this)
925 { 924 {
926 925 if (TerrainUploader == null)
927 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
928 lock (TerrainUploader)
929 { 926 {
927 m_log.DebugFormat("Starting to receive uploaded terrain");
928 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
930 remote_client.OnXferReceive += TerrainUploader.XferReceive; 929 remote_client.OnXferReceive += TerrainUploader.XferReceive;
931 remote_client.OnAbortXfer += AbortTerrainXferHandler; 930 remote_client.OnAbortXfer += AbortTerrainXferHandler;
932 TerrainUploader.TerrainUploadDone += HandleTerrainApplication; 931 TerrainUploader.TerrainUploadDone += HandleTerrainApplication;
932 TerrainUploader.RequestStartXfer(remote_client);
933 }
934 else
935 {
936 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!");
933 } 937 }
934 TerrainUploader.RequestStartXfer(remote_client);
935
936 } 938 }
937 else 939 }
940
941 public bool IsTerrainXfer(ulong xferID)
942 {
943 lock (this)
938 { 944 {
939 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!"); 945 if (TerrainUploader == null)
946 return false;
947 else
948 return TerrainUploader.XferID == xferID;
940 } 949 }
941 } 950 }
942 951
@@ -1221,7 +1230,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1221 client.OnEstateRestartSimRequest += handleEstateRestartSimRequest; 1230 client.OnEstateRestartSimRequest += handleEstateRestartSimRequest;
1222 client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest; 1231 client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest;
1223 client.OnEstateChangeInfo += handleEstateChangeInfo; 1232 client.OnEstateChangeInfo += handleEstateChangeInfo;
1224 client.OnEstateManageTelehub += handleOnEstateManageTelehub; 1233 client.OnEstateManageTelehub += HandleOnEstateManageTelehub;
1225 client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest; 1234 client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest;
1226 client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage; 1235 client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage;
1227 client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage; 1236 client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage;
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
index b8d8b10..2d74eaf 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
@@ -78,7 +78,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
78 /// <param name="data"></param> 78 /// <param name="data"></param>
79 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) 79 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
80 { 80 {
81 if (mXferID == xferID) 81 if (mXferID != xferID)
82 return;
83
84 lock (this)
82 { 85 {
83 if (m_asset.Data.Length > 1) 86 if (m_asset.Data.Length > 1)
84 { 87 {
@@ -99,7 +102,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
99 if ((packetID & 0x80000000) != 0) 102 if ((packetID & 0x80000000) != 0)
100 { 103 {
101 SendCompleteMessage(remoteClient); 104 SendCompleteMessage(remoteClient);
102
103 } 105 }
104 } 106 }
105 } 107 }
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs
new file mode 100644
index 0000000..73e706c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs
@@ -0,0 +1,218 @@
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;
31
32using OpenSim.Services.Interfaces;
33using GridRegion = OpenSim.Services.Interfaces.GridRegion;
34using OpenSim.Server.Base;
35using OpenSim.Framework.Servers.HttpServer;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Scenes;
38
39using OpenMetaverse;
40using log4net;
41
42namespace OpenSim.Region.CoreModules.World.Estate
43{
44 public class EstateConnector
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 protected XEstateModule m_EstateModule;
49
50 public EstateConnector(XEstateModule module)
51 {
52 m_EstateModule = module;
53 }
54
55 public void SendTeleportHomeOneUser(uint EstateID, UUID PreyID)
56 {
57 Dictionary<string, object> sendData = new Dictionary<string, object>();
58 sendData["METHOD"] = "teleport_home_one_user";
59
60 sendData["EstateID"] = EstateID.ToString();
61 sendData["PreyID"] = PreyID.ToString();
62
63 SendToEstate(EstateID, sendData);
64 }
65
66 public void SendTeleportHomeAllUsers(uint EstateID)
67 {
68 Dictionary<string, object> sendData = new Dictionary<string, object>();
69 sendData["METHOD"] = "teleport_home_all_users";
70
71 sendData["EstateID"] = EstateID.ToString();
72
73 SendToEstate(EstateID, sendData);
74 }
75
76 public bool SendUpdateCovenant(uint EstateID, UUID CovenantID)
77 {
78 Dictionary<string, object> sendData = new Dictionary<string, object>();
79 sendData["METHOD"] = "update_covenant";
80
81 sendData["CovenantID"] = CovenantID.ToString();
82 sendData["EstateID"] = EstateID.ToString();
83
84 // Handle local regions locally
85 //
86 foreach (Scene s in m_EstateModule.Scenes)
87 {
88 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
89 s.RegionInfo.RegionSettings.Covenant = CovenantID;
90// s.ReloadEstateData();
91 }
92
93 SendToEstate(EstateID, sendData);
94
95 return true;
96 }
97
98 public bool SendUpdateEstate(uint EstateID)
99 {
100 Dictionary<string, object> sendData = new Dictionary<string, object>();
101 sendData["METHOD"] = "update_estate";
102
103 sendData["EstateID"] = EstateID.ToString();
104
105 // Handle local regions locally
106 //
107 foreach (Scene s in m_EstateModule.Scenes)
108 {
109 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
110 s.ReloadEstateData();
111 }
112
113 SendToEstate(EstateID, sendData);
114
115 return true;
116 }
117
118 public void SendEstateMessage(uint EstateID, UUID FromID, string FromName, string Message)
119 {
120 Dictionary<string, object> sendData = new Dictionary<string, object>();
121 sendData["METHOD"] = "estate_message";
122
123 sendData["EstateID"] = EstateID.ToString();
124 sendData["FromID"] = FromID.ToString();
125 sendData["FromName"] = FromName;
126 sendData["Message"] = Message;
127
128 SendToEstate(EstateID, sendData);
129 }
130
131 private void SendToEstate(uint EstateID, Dictionary<string, object> sendData)
132 {
133 List<UUID> regions = m_EstateModule.Scenes[0].GetEstateRegions((int)EstateID);
134
135 UUID ScopeID = UUID.Zero;
136
137 // Handle local regions locally
138 //
139 lock (m_EstateModule.Scenes)
140 {
141 foreach (Scene s in m_EstateModule.Scenes)
142 {
143 if (regions.Contains(s.RegionInfo.RegionID))
144 {
145 // All regions in one estate are in the same scope.
146 // Use that scope.
147 //
148 ScopeID = s.RegionInfo.ScopeID;
149 regions.Remove(s.RegionInfo.RegionID);
150 }
151 }
152 }
153
154 // Our own region should always be in the above list.
155 // In a standalone this would not be true. But then,
156 // Scope ID is not relevat there. Use first scope.
157 //
158 if (ScopeID == UUID.Zero)
159 ScopeID = m_EstateModule.Scenes[0].RegionInfo.ScopeID;
160
161 // Don't send to the same instance twice
162 //
163 List<string> done = new List<string>();
164
165 // Send to remote regions
166 //
167 foreach (UUID regionID in regions)
168 {
169 GridRegion region = m_EstateModule.Scenes[0].GridService.GetRegionByUUID(ScopeID, regionID);
170 if (region != null)
171 {
172 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort;
173 if (done.Contains(url))
174 continue;
175
176 Call(region, sendData);
177 done.Add(url);
178 }
179 }
180 }
181
182 private bool Call(GridRegion region, Dictionary<string, object> sendData)
183 {
184 string reqString = ServerUtils.BuildQueryString(sendData);
185 // m_log.DebugFormat("[XESTATE CONNECTOR]: queryString = {0}", reqString);
186 try
187 {
188 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort;
189 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
190 url + "/estate",
191 reqString);
192 if (reply != string.Empty)
193 {
194 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
195
196 if (replyData.ContainsKey("RESULT"))
197 {
198 if (replyData["RESULT"].ToString().ToLower() == "true")
199 return true;
200 else
201 return false;
202 }
203 else
204 m_log.DebugFormat("[XESTATE CONNECTOR]: reply data does not contain result field");
205
206 }
207 else
208 m_log.DebugFormat("[XESTATE CONNECTOR]: received empty reply");
209 }
210 catch (Exception e)
211 {
212 m_log.DebugFormat("[XESTATE CONNECTOR]: Exception when contacting remote sim: {0}", e.Message);
213 }
214
215 return false;
216 }
217 }
218}
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs
new file mode 100644
index 0000000..f54ab2c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs
@@ -0,0 +1,256 @@
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 log4net;
33using Nini.Config;
34using Nwc.XmlRpc;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Framework.Communications;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Server.Base;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using Mono.Addins;
45
46namespace OpenSim.Region.CoreModules.World.Estate
47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEstate")]
49 public class XEstateModule : ISharedRegionModule
50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 protected List<Scene> m_Scenes = new List<Scene>();
54 protected bool m_InInfoUpdate = false;
55
56 public bool InInfoUpdate
57 {
58 get { return m_InInfoUpdate; }
59 set { m_InInfoUpdate = value; }
60 }
61
62 public List<Scene> Scenes
63 {
64 get { return m_Scenes; }
65 }
66
67 protected EstateConnector m_EstateConnector;
68
69 public void Initialise(IConfigSource config)
70 {
71 int port = 0;
72
73 IConfig estateConfig = config.Configs["Estate"];
74 if (estateConfig != null)
75 {
76 port = estateConfig.GetInt("Port", 0);
77 }
78
79 m_EstateConnector = new EstateConnector(this);
80
81 // Instantiate the request handler
82 IHttpServer server = MainServer.GetHttpServer((uint)port);
83 server.AddStreamHandler(new EstateRequestHandler(this));
84 }
85
86 public void PostInitialise()
87 {
88 }
89
90 public void Close()
91 {
92 }
93
94 public void AddRegion(Scene scene)
95 {
96 lock (m_Scenes)
97 m_Scenes.Add(scene);
98
99 scene.EventManager.OnNewClient += OnNewClient;
100 }
101
102 public void RegionLoaded(Scene scene)
103 {
104 IEstateModule em = scene.RequestModuleInterface<IEstateModule>();
105
106 em.OnRegionInfoChange += OnRegionInfoChange;
107 em.OnEstateInfoChange += OnEstateInfoChange;
108 em.OnEstateMessage += OnEstateMessage;
109 }
110
111 public void RemoveRegion(Scene scene)
112 {
113 scene.EventManager.OnNewClient -= OnNewClient;
114
115 lock (m_Scenes)
116 m_Scenes.Remove(scene);
117 }
118
119 public string Name
120 {
121 get { return "EstateModule"; }
122 }
123
124 public Type ReplaceableInterface
125 {
126 get { return null; }
127 }
128
129 private Scene FindScene(UUID RegionID)
130 {
131 foreach (Scene s in Scenes)
132 {
133 if (s.RegionInfo.RegionID == RegionID)
134 return s;
135 }
136
137 return null;
138 }
139
140 private void OnRegionInfoChange(UUID RegionID)
141 {
142 Scene s = FindScene(RegionID);
143 if (s == null)
144 return;
145
146 if (!m_InInfoUpdate)
147 m_EstateConnector.SendUpdateCovenant(s.RegionInfo.EstateSettings.EstateID, s.RegionInfo.RegionSettings.Covenant);
148 }
149
150 private void OnEstateInfoChange(UUID RegionID)
151 {
152 Scene s = FindScene(RegionID);
153 if (s == null)
154 return;
155
156 if (!m_InInfoUpdate)
157 m_EstateConnector.SendUpdateEstate(s.RegionInfo.EstateSettings.EstateID);
158 }
159
160 private void OnEstateMessage(UUID RegionID, UUID FromID, string FromName, string Message)
161 {
162 Scene senderScenes = FindScene(RegionID);
163 if (senderScenes == null)
164 return;
165
166 uint estateID = senderScenes.RegionInfo.EstateSettings.EstateID;
167
168 foreach (Scene s in Scenes)
169 {
170 if (s.RegionInfo.EstateSettings.EstateID == estateID)
171 {
172 IDialogModule dm = s.RequestModuleInterface<IDialogModule>();
173
174 if (dm != null)
175 {
176 dm.SendNotificationToUsersInRegion(FromID, FromName,
177 Message);
178 }
179 }
180 }
181 if (!m_InInfoUpdate)
182 m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message);
183 }
184
185 private void OnNewClient(IClientAPI client)
186 {
187 client.OnEstateTeleportOneUserHomeRequest += OnEstateTeleportOneUserHomeRequest;
188 client.OnEstateTeleportAllUsersHomeRequest += OnEstateTeleportAllUsersHomeRequest;
189
190 }
191
192 private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey)
193 {
194 if (prey == UUID.Zero)
195 return;
196
197 if (!(client.Scene is Scene))
198 return;
199
200 Scene scene = (Scene)client.Scene;
201
202 uint estateID = scene.RegionInfo.EstateSettings.EstateID;
203
204 if (!scene.Permissions.CanIssueEstateCommand(client.AgentId, false))
205 return;
206
207 foreach (Scene s in Scenes)
208 {
209 if (s == scene)
210 continue; // Already handles by estate module
211 if (s.RegionInfo.EstateSettings.EstateID != estateID)
212 continue;
213
214 ScenePresence p = scene.GetScenePresence(prey);
215 if (p != null && !p.IsChildAgent)
216 {
217 p.ControllingClient.SendTeleportStart(16);
218 scene.TeleportClientHome(prey, p.ControllingClient);
219 }
220 }
221
222 m_EstateConnector.SendTeleportHomeOneUser(estateID, prey);
223 }
224
225 private void OnEstateTeleportAllUsersHomeRequest(IClientAPI client, UUID invoice, UUID senderID)
226 {
227 if (!(client.Scene is Scene))
228 return;
229
230 Scene scene = (Scene)client.Scene;
231
232 uint estateID = scene.RegionInfo.EstateSettings.EstateID;
233
234 if (!scene.Permissions.CanIssueEstateCommand(client.AgentId, false))
235 return;
236
237 foreach (Scene s in Scenes)
238 {
239 if (s == scene)
240 continue; // Already handles by estate module
241 if (s.RegionInfo.EstateSettings.EstateID != estateID)
242 continue;
243
244 scene.ForEachScenePresence(delegate(ScenePresence p) {
245 if (p != null && !p.IsChildAgent)
246 {
247 p.ControllingClient.SendTeleportStart(16);
248 scene.TeleportClientHome(p.ControllingClient.AgentId, p.ControllingClient);
249 }
250 });
251 }
252
253 m_EstateConnector.SendTeleportHomeAllUsers(estateID);
254 }
255 }
256}
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs
new file mode 100644
index 0000000..2366767
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs
@@ -0,0 +1,298 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Xml;
33
34using OpenSim.Framework;
35using OpenSim.Server.Base;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Region.Framework.Interfaces;
39
40using OpenMetaverse;
41using log4net;
42
43namespace OpenSim.Region.CoreModules.World.Estate
44{
45 public class EstateRequestHandler : BaseStreamHandler
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 protected XEstateModule m_EstateModule;
50 protected Object m_RequestLock = new Object();
51
52 public EstateRequestHandler(XEstateModule fmodule)
53 : base("POST", "/estate")
54 {
55 m_EstateModule = fmodule;
56 }
57
58 protected override byte[] ProcessRequest(string path, Stream requestData,
59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
60 {
61 StreamReader sr = new StreamReader(requestData);
62 string body = sr.ReadToEnd();
63 sr.Close();
64 body = body.Trim();
65
66 m_log.DebugFormat("[XESTATE HANDLER]: query String: {0}", body);
67
68 try
69 {
70 lock (m_RequestLock)
71 {
72 Dictionary<string, object> request =
73 ServerUtils.ParseQueryString(body);
74
75 if (!request.ContainsKey("METHOD"))
76 return FailureResult();
77
78 string method = request["METHOD"].ToString();
79 request.Remove("METHOD");
80
81 try
82 {
83 m_EstateModule.InInfoUpdate = false;
84
85 switch (method)
86 {
87 case "update_covenant":
88 return UpdateCovenant(request);
89 case "update_estate":
90 return UpdateEstate(request);
91 case "estate_message":
92 return EstateMessage(request);
93 case "teleport_home_one_user":
94 return TeleportHomeOneUser(request);
95 case "teleport_home_all_users":
96 return TeleportHomeAllUsers(request);
97 }
98 }
99 finally
100 {
101 m_EstateModule.InInfoUpdate = false;
102 }
103 }
104 }
105 catch (Exception e)
106 {
107 m_log.Debug("[XESTATE]: Exception {0}" + e.ToString());
108 }
109
110 return FailureResult();
111 }
112
113 byte[] TeleportHomeAllUsers(Dictionary<string, object> request)
114 {
115 UUID PreyID = UUID.Zero;
116 int EstateID = 0;
117
118 if (!request.ContainsKey("EstateID"))
119 return FailureResult();
120
121 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
122 return FailureResult();
123
124 foreach (Scene s in m_EstateModule.Scenes)
125 {
126 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
127 {
128 s.ForEachScenePresence(delegate(ScenePresence p) {
129 if (p != null && !p.IsChildAgent)
130 {
131 p.ControllingClient.SendTeleportStart(16);
132 s.TeleportClientHome(p.ControllingClient.AgentId, p.ControllingClient);
133 }
134 });
135 }
136 }
137
138 return SuccessResult();
139 }
140
141 byte[] TeleportHomeOneUser(Dictionary<string, object> request)
142 {
143 UUID PreyID = UUID.Zero;
144 int EstateID = 0;
145
146 if (!request.ContainsKey("PreyID") ||
147 !request.ContainsKey("EstateID"))
148 {
149 return FailureResult();
150 }
151
152 if (!UUID.TryParse(request["PreyID"].ToString(), out PreyID))
153 return FailureResult();
154
155 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
156 return FailureResult();
157
158 foreach (Scene s in m_EstateModule.Scenes)
159 {
160 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
161 {
162 ScenePresence p = s.GetScenePresence(PreyID);
163 if (p != null && !p.IsChildAgent)
164 {
165 p.ControllingClient.SendTeleportStart(16);
166 s.TeleportClientHome(PreyID, p.ControllingClient);
167 }
168 }
169 }
170
171 return SuccessResult();
172 }
173
174 byte[] EstateMessage(Dictionary<string, object> request)
175 {
176 UUID FromID = UUID.Zero;
177 string FromName = String.Empty;
178 string Message = String.Empty;
179 int EstateID = 0;
180
181 if (!request.ContainsKey("FromID") ||
182 !request.ContainsKey("FromName") ||
183 !request.ContainsKey("Message") ||
184 !request.ContainsKey("EstateID"))
185 {
186 return FailureResult();
187 }
188
189 if (!UUID.TryParse(request["FromID"].ToString(), out FromID))
190 return FailureResult();
191
192 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
193 return FailureResult();
194
195 FromName = request["FromName"].ToString();
196 Message = request["Message"].ToString();
197
198 foreach (Scene s in m_EstateModule.Scenes)
199 {
200 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
201 {
202 IDialogModule dm = s.RequestModuleInterface<IDialogModule>();
203
204 if (dm != null)
205 {
206 dm.SendNotificationToUsersInRegion(FromID, FromName,
207 Message);
208 }
209 }
210 }
211
212 return SuccessResult();
213 }
214
215 byte[] UpdateCovenant(Dictionary<string, object> request)
216 {
217 UUID CovenantID = UUID.Zero;
218 int EstateID = 0;
219
220 if (!request.ContainsKey("CovenantID") || !request.ContainsKey("EstateID"))
221 return FailureResult();
222
223 if (!UUID.TryParse(request["CovenantID"].ToString(), out CovenantID))
224 return FailureResult();
225
226 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
227 return FailureResult();
228
229 foreach (Scene s in m_EstateModule.Scenes)
230 {
231 if (s.RegionInfo.EstateSettings.EstateID == (uint)EstateID)
232 s.RegionInfo.RegionSettings.Covenant = CovenantID;
233 }
234
235 return SuccessResult();
236 }
237
238 byte[] UpdateEstate(Dictionary<string, object> request)
239 {
240 int EstateID = 0;
241
242 if (!request.ContainsKey("EstateID"))
243 return FailureResult();
244 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
245 return FailureResult();
246
247 foreach (Scene s in m_EstateModule.Scenes)
248 {
249 if (s.RegionInfo.EstateSettings.EstateID == (uint)EstateID)
250 s.ReloadEstateData();
251 }
252 return SuccessResult();
253 }
254
255 private byte[] FailureResult()
256 {
257 return BoolResult(false);
258 }
259
260 private byte[] SuccessResult()
261 {
262 return BoolResult(true);
263 }
264
265 private byte[] BoolResult(bool value)
266 {
267 XmlDocument doc = new XmlDocument();
268
269 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
270 "", "");
271
272 doc.AppendChild(xmlnode);
273
274 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
275 "");
276
277 doc.AppendChild(rootElement);
278
279 XmlElement result = doc.CreateElement("", "RESULT", "");
280 result.AppendChild(doc.CreateTextNode(value.ToString()));
281
282 rootElement.AppendChild(result);
283
284 return DocToBytes(doc);
285 }
286
287 private byte[] DocToBytes(XmlDocument doc)
288 {
289 MemoryStream ms = new MemoryStream();
290 XmlTextWriter xw = new XmlTextWriter(ms, null);
291 xw.Formatting = Formatting.Indented;
292 doc.WriteTo(xw);
293 xw.Flush();
294
295 return ms.ToArray();
296 }
297 }
298}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 4e21724..0e2aba9 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -42,7 +42,6 @@ using OpenSim.Framework.Capabilities;
42using OpenSim.Framework.Console; 42using OpenSim.Framework.Console;
43using OpenSim.Framework.Servers; 43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer; 44using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
46using OpenSim.Region.Framework.Interfaces; 45using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes; 46using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Physics.Manager; 47using OpenSim.Region.Physics.Manager;
@@ -70,10 +69,10 @@ namespace OpenSim.Region.CoreModules.World.Land
70 69
71 private LandChannel landChannel; 70 private LandChannel landChannel;
72 private Scene m_scene; 71 private Scene m_scene;
73 protected Commander m_commander = new Commander("land");
74 72
75 protected IUserManagement m_userManager; 73 protected IUserManagement m_userManager;
76 protected IPrimCountModule m_primCountModule; 74 protected IPrimCountModule m_primCountModule;
75 protected IDialogModule m_Dialog;
77 76
78 // Minimum for parcels to work is 64m even if we don't actually use them. 77 // Minimum for parcels to work is 64m even if we don't actually use them.
79 #pragma warning disable 0429 78 #pragma warning disable 0429
@@ -147,52 +146,33 @@ namespace OpenSim.Region.CoreModules.World.Land
147 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; 146 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
148 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; 147 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan;
149 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps; 148 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps;
150 m_scene.EventManager.OnPluginConsole += EventManagerOnPluginConsole;
151 149
152 lock (m_scene) 150 lock (m_scene)
153 { 151 {
154 m_scene.LandChannel = (ILandChannel)landChannel; 152 m_scene.LandChannel = (ILandChannel)landChannel;
155 } 153 }
156 154
157 InstallInterfaces(); 155 RegisterCommands();
158 } 156 }
159 157
160 public void RegionLoaded(Scene scene) 158 public void RegionLoaded(Scene scene)
161 { 159 {
162 m_userManager = m_scene.RequestModuleInterface<IUserManagement>(); 160 m_userManager = m_scene.RequestModuleInterface<IUserManagement>();
163 m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>(); 161 m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>();
162 m_Dialog = m_scene.RequestModuleInterface<IDialogModule>();
164 } 163 }
165 164
166 public void RemoveRegion(Scene scene) 165 public void RemoveRegion(Scene scene)
167 { 166 {
168 // TODO: Also release other event manager listeners here 167 // TODO: Release event manager listeners here
169
170 m_scene.EventManager.OnPluginConsole -= EventManagerOnPluginConsole;
171 m_scene.UnregisterModuleCommander(m_commander.Name);
172 } 168 }
173 169
174 /// <summary> 170// private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason)
175 /// Processes commandline input. Do not call directly. 171// {
176 /// </summary> 172// ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y);
177 /// <param name="args">Commandline arguments</param> 173// reason = "You are not allowed to enter this sim.";
178 protected void EventManagerOnPluginConsole(string[] args) 174// return nearestParcel != null;
179 { 175// }
180 if (args[0] == "land")
181 {
182 if (args.Length == 1)
183 {
184 m_commander.ProcessConsoleCommand("help", new string[0]);
185 return;
186 }
187
188 string[] tmpArgs = new string[args.Length - 2];
189 int i;
190 for (i = 2; i < args.Length; i++)
191 tmpArgs[i - 2] = args[i];
192
193 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
194 }
195 }
196 176
197 void EventManagerOnNewClient(IClientAPI client) 177 void EventManagerOnNewClient(IClientAPI client)
198 { 178 {
@@ -213,6 +193,7 @@ namespace OpenSim.Region.CoreModules.World.Land
213 client.OnPreAgentUpdate += ClientOnPreAgentUpdate; 193 client.OnPreAgentUpdate += ClientOnPreAgentUpdate;
214 client.OnParcelEjectUser += ClientOnParcelEjectUser; 194 client.OnParcelEjectUser += ClientOnParcelEjectUser;
215 client.OnParcelFreezeUser += ClientOnParcelFreezeUser; 195 client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
196 client.OnSetStartLocationRequest += ClientOnSetHome;
216 197
217 EntityBase presenceEntity; 198 EntityBase presenceEntity;
218 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) 199 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
@@ -1896,44 +1877,131 @@ namespace OpenSim.Region.CoreModules.World.Land
1896 land.LandData.ParcelAccessList.Add(entry); 1877 land.LandData.ParcelAccessList.Add(entry);
1897 } 1878 }
1898 } 1879 }
1899 1880
1900 protected void InstallInterfaces() 1881 /// <summary>
1882 /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in
1883 /// </summary>
1884 /// <param name="remoteClient"></param>
1885 /// <param name="regionHandle"></param>
1886 /// <param name="position"></param>
1887 /// <param name="lookAt"></param>
1888 /// <param name="flags"></param>
1889 public virtual void ClientOnSetHome(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
1890 {
1891 // Let's find the parcel in question
1892 ILandObject land = landChannel.GetLandObject(position);
1893 if (land == null || m_scene.GridUserService == null)
1894 {
1895 m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed.");
1896 return;
1897 }
1898
1899 // Gather some data
1900 ulong gpowers = remoteClient.GetGroupPowers(land.LandData.GroupID);
1901 SceneObjectGroup telehub = null;
1902 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero)
1903 // Does the telehub exist in the scene?
1904 telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
1905
1906 // Can the user set home here?
1907 if (// (a) gods and land managers can set home
1908 m_scene.Permissions.IsAdministrator(remoteClient.AgentId) ||
1909 m_scene.Permissions.IsGod(remoteClient.AgentId) ||
1910 // (b) land owners can set home
1911 remoteClient.AgentId == land.LandData.OwnerID ||
1912 // (c) members of the land-associated group in roles that can set home
1913 ((gpowers & (ulong)GroupPowers.AllowSetHome) == (ulong)GroupPowers.AllowSetHome) ||
1914 // (d) parcels with telehubs can be the home of anyone
1915 (telehub != null && land.ContainsPoint((int)telehub.AbsolutePosition.X, (int)telehub.AbsolutePosition.Y)))
1916 {
1917 if (m_scene.GridUserService.SetHome(remoteClient.AgentId.ToString(), land.RegionUUID, position, lookAt))
1918 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
1919 m_Dialog.SendAlertToUser(remoteClient, "Home position set.");
1920 else
1921 m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed.");
1922 }
1923 else
1924 m_Dialog.SendAlertToUser(remoteClient, "You are not allowed to set your home location in this parcel.");
1925 }
1926
1927 protected void RegisterCommands()
1901 { 1928 {
1902 Command clearCommand 1929 ICommands commands = MainConsole.Instance.Commands;
1903 = new Command("clear", CommandIntentions.COMMAND_HAZARDOUS, ClearCommand, "Clears all the parcels from the region.");
1904 Command showCommand
1905 = new Command("show", CommandIntentions.COMMAND_STATISTICAL, ShowParcelsCommand, "Shows all parcels on the region.");
1906 1930
1907 m_commander.RegisterCommand("clear", clearCommand); 1931 commands.AddCommand(
1908 m_commander.RegisterCommand("show", showCommand); 1932 "Land", false, "land clear",
1933 "land clear",
1934 "Clear all the parcels from the region.",
1935 "Command will ask for confirmation before proceeding.",
1936 HandleClearCommand);
1909 1937
1910 // Add this to our scene so scripts can call these functions 1938 commands.AddCommand(
1911 m_scene.RegisterModuleCommander(m_commander); 1939 "Land", false, "land show",
1940 "land show [<local-land-id>]",
1941 "Show information about the parcels on the region.",
1942 "If no local land ID is given, then summary information about all the parcels is shown.\n"
1943 + "If a local land ID is given then full information about that parcel is shown.",
1944 HandleShowCommand);
1912 } 1945 }
1913 1946
1914 protected void ClearCommand(Object[] args) 1947 protected void HandleClearCommand(string module, string[] args)
1915 { 1948 {
1949 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
1950 return;
1951
1916 string response = MainConsole.Instance.CmdPrompt( 1952 string response = MainConsole.Instance.CmdPrompt(
1917 string.Format( 1953 string.Format(
1918 "Are you sure that you want to clear all land parcels from {0} (y or n)", 1954 "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name),
1919 m_scene.RegionInfo.RegionName),
1920 "n"); 1955 "n");
1921 1956
1922 if (response.ToLower() == "y") 1957 if (response.ToLower() == "y")
1923 { 1958 {
1924 Clear(true); 1959 Clear(true);
1925 MainConsole.Instance.OutputFormat("Cleared all parcels from {0}", m_scene.RegionInfo.RegionName); 1960 MainConsole.Instance.OutputFormat("Cleared all parcels from {0}", m_scene.Name);
1926 } 1961 }
1927 else 1962 else
1928 { 1963 {
1929 MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.RegionInfo.RegionName); 1964 MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.Name);
1930 } 1965 }
1931 } 1966 }
1932 1967
1933 protected void ShowParcelsCommand(Object[] args) 1968 protected void HandleShowCommand(string module, string[] args)
1934 { 1969 {
1935 StringBuilder report = new StringBuilder(); 1970 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
1936 1971 return;
1972
1973 StringBuilder report = new StringBuilder();
1974
1975 if (args.Length <= 2)
1976 {
1977 AppendParcelsSummaryReport(report);
1978 }
1979 else
1980 {
1981 int landLocalId;
1982
1983 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId))
1984 return;
1985
1986 ILandObject lo;
1987
1988 lock (m_landList)
1989 {
1990 if (!m_landList.TryGetValue(landLocalId, out lo))
1991 {
1992 MainConsole.Instance.OutputFormat("No parcel found with local ID {0}", landLocalId);
1993 return;
1994 }
1995 }
1996
1997 AppendParcelReport(report, lo);
1998 }
1999
2000 MainConsole.Instance.Output(report.ToString());
2001 }
2002
2003 private void AppendParcelsSummaryReport(StringBuilder report)
2004 {
1937 report.AppendFormat("Land information for {0}\n", m_scene.RegionInfo.RegionName); 2005 report.AppendFormat("Land information for {0}\n", m_scene.RegionInfo.RegionName);
1938 report.AppendFormat( 2006 report.AppendFormat(
1939 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n", 2007 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n",
@@ -1979,6 +2047,69 @@ namespace OpenSim.Region.CoreModules.World.Land
1979 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition); 2047 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
1980 } 2048 }
1981 } 2049 }
2050 }
2051
2052 private void AppendParcelReport(StringBuilder report, ILandObject lo)
2053 {
2054 LandData ld = lo.LandData;
2055
2056 ConsoleDisplayList cdl = new ConsoleDisplayList();
2057 cdl.AddRow("Parcel name", ld.Name);
2058 cdl.AddRow("Local ID", ld.LocalID);
2059 cdl.AddRow("Description", ld.Description);
2060 cdl.AddRow("Snapshot ID", ld.SnapshotID);
2061 cdl.AddRow("Area", ld.Area);
2062 cdl.AddRow("Starts", lo.StartPoint);
2063 cdl.AddRow("Ends", lo.EndPoint);
2064 cdl.AddRow("AABB Min", ld.AABBMin);
2065 cdl.AddRow("AABB Max", ld.AABBMax);
2066
2067 cdl.AddRow("Owner", m_userManager.GetUserName(ld.OwnerID));
2068 cdl.AddRow("Is group owned?", ld.IsGroupOwned);
2069 cdl.AddRow("GroupID", ld.GroupID);
2070
2071 cdl.AddRow("Status", ld.Status);
2072 cdl.AddRow("Flags", (ParcelFlags)ld.Flags);
2073
2074 cdl.AddRow("Landing Type", (LandingType)ld.LandingType);
2075 cdl.AddRow("User Location", ld.UserLocation);
2076 cdl.AddRow("User look at", ld.UserLookAt);
2077
2078 cdl.AddRow("Other clean time", ld.OtherCleanTime);
2079
2080 cdl.AddRow("Max Prims", lo.GetParcelMaxPrimCount());
2081 IPrimCounts pc = lo.PrimCounts;
2082 cdl.AddRow("Owner Prims", pc.Owner);
2083 cdl.AddRow("Group Prims", pc.Group);
2084 cdl.AddRow("Other Prims", pc.Others);
2085 cdl.AddRow("Selected Prims", pc.Selected);
2086 cdl.AddRow("Total Prims", pc.Total);
2087
2088 cdl.AddRow("Music URL", ld.MusicURL);
2089 cdl.AddRow("Obscure Music", ld.ObscureMusic);
2090
2091 cdl.AddRow("Media ID", ld.MediaID);
2092 cdl.AddRow("Media Autoscale", Convert.ToBoolean(ld.MediaAutoScale));
2093 cdl.AddRow("Media URL", ld.MediaURL);
2094 cdl.AddRow("Media Type", ld.MediaType);
2095 cdl.AddRow("Media Description", ld.MediaDescription);
2096 cdl.AddRow("Media Width", ld.MediaWidth);
2097 cdl.AddRow("Media Height", ld.MediaHeight);
2098 cdl.AddRow("Media Loop", ld.MediaLoop);
2099 cdl.AddRow("Obscure Media", ld.ObscureMedia);
2100
2101 cdl.AddRow("Parcel Category", ld.Category);
2102
2103 cdl.AddRow("Claim Date", ld.ClaimDate);
2104 cdl.AddRow("Claim Price", ld.ClaimPrice);
2105 cdl.AddRow("Pass Hours", ld.PassHours);
2106 cdl.AddRow("Pass Price", ld.PassPrice);
2107
2108 cdl.AddRow("Auction ID", ld.AuctionID);
2109 cdl.AddRow("Authorized Buyer ID", ld.AuthBuyerID);
2110 cdl.AddRow("Sale Price", ld.SalePrice);
2111
2112 cdl.AddToStringBuilder(report);
1982 } 2113 }
1983 } 2114 }
1984} 2115}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 2eafd44..74c2144 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -82,14 +82,14 @@ namespace OpenSim.Region.CoreModules.World.Land
82 82
83 set { m_landData = value; } 83 set { m_landData = value; }
84 } 84 }
85 85
86 public IPrimCounts PrimCounts { get; set; } 86 public IPrimCounts PrimCounts { get; set; }
87 87
88 public UUID RegionUUID 88 public UUID RegionUUID
89 { 89 {
90 get { return m_scene.RegionInfo.RegionID; } 90 get { return m_scene.RegionInfo.RegionID; }
91 } 91 }
92 92
93 public Vector3 StartPoint 93 public Vector3 StartPoint
94 { 94 {
95 get 95 get
@@ -102,11 +102,11 @@ namespace OpenSim.Region.CoreModules.World.Land
102 return new Vector3(x * 4, y * 4, 0); 102 return new Vector3(x * 4, y * 4, 0);
103 } 103 }
104 } 104 }
105 105
106 return new Vector3(-1, -1, -1); 106 return new Vector3(-1, -1, -1);
107 } 107 }
108 } 108 }
109 109
110 public Vector3 EndPoint 110 public Vector3 EndPoint
111 { 111 {
112 get 112 get
@@ -117,15 +117,15 @@ namespace OpenSim.Region.CoreModules.World.Land
117 { 117 {
118 if (LandBitmap[x, y]) 118 if (LandBitmap[x, y])
119 { 119 {
120 return new Vector3(x * 4, y * 4, 0); 120 return new Vector3(x * 4 + 4, y * 4 + 4, 0);
121 } 121 }
122 } 122 }
123 } 123 }
124 124
125 return new Vector3(-1, -1, -1); 125 return new Vector3(-1, -1, -1);
126 } 126 }
127 } 127 }
128 128
129 #region Constructors 129 #region Constructors
130 130
131 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 131 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
@@ -249,13 +249,6 @@ namespace OpenSim.Region.CoreModules.World.Land
249 if (estateModule != null) 249 if (estateModule != null)
250 regionFlags = estateModule.GetRegionFlags(); 250 regionFlags = estateModule.GetRegionFlags();
251 251
252 // In a perfect world, this would have worked.
253 //
254// if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0)
255// regionFlags |= (uint)RegionFlags.AllowLandmark;
256// if (landData.OwnerID == remote_client.AgentId)
257// regionFlags |= (uint)RegionFlags.AllowSetHome;
258
259 int seq_id; 252 int seq_id;
260 if (snap_selection && (sequence_id == 0)) 253 if (snap_selection && (sequence_id == 0))
261 { 254 {
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index 40638f8..bc52a43 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
55 public struct DrawStruct 55 public struct DrawStruct
56 { 56 {
57 public DrawRoutine dr; 57 public DrawRoutine dr;
58 public Rectangle rect; 58// public Rectangle rect;
59 public SolidBrush brush; 59 public SolidBrush brush;
60 public face[] trns; 60 public face[] trns;
61 } 61 }
@@ -119,6 +119,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
119 { 119 {
120 mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID); 120 mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID);
121 } 121 }
122
122 return mapbmp; 123 return mapbmp;
123 } 124 }
124 125
@@ -127,7 +128,10 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
127 try 128 try
128 { 129 {
129 using (Bitmap mapbmp = CreateMapTile()) 130 using (Bitmap mapbmp = CreateMapTile())
130 return OpenJPEG.EncodeFromImage(mapbmp, true); 131 {
132 if (mapbmp != null)
133 return OpenJPEG.EncodeFromImage(mapbmp, true);
134 }
131 } 135 }
132 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke 136 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke
133 { 137 {
@@ -277,321 +281,331 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
277 tc = Environment.TickCount; 281 tc = Environment.TickCount;
278 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); 282 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
279 EntityBase[] objs = whichScene.GetEntities(); 283 EntityBase[] objs = whichScene.GetEntities();
280 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
281 //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
282 List<float> z_sortheights = new List<float>(); 284 List<float> z_sortheights = new List<float>();
283 List<uint> z_localIDs = new List<uint>(); 285 List<uint> z_localIDs = new List<uint>();
286 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
284 287
285 lock (objs) 288 try
286 { 289 {
287 foreach (EntityBase obj in objs) 290 //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
291
292 lock (objs)
288 { 293 {
289 // Only draw the contents of SceneObjectGroup 294 foreach (EntityBase obj in objs)
290 if (obj is SceneObjectGroup)
291 { 295 {
292 SceneObjectGroup mapdot = (SceneObjectGroup)obj; 296 // Only draw the contents of SceneObjectGroup
293 Color mapdotspot = Color.Gray; // Default color when prim color is white 297 if (obj is SceneObjectGroup)
294
295 // Loop over prim in group
296 foreach (SceneObjectPart part in mapdot.Parts)
297 { 298 {
298 if (part == null) 299 SceneObjectGroup mapdot = (SceneObjectGroup)obj;
299 continue; 300 Color mapdotspot = Color.Gray; // Default color when prim color is white
300 301
301 // Draw if the object is at least 1 meter wide in any direction 302 // Loop over prim in group
302 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f) 303 foreach (SceneObjectPart part in mapdot.Parts)
303 { 304 {
304 // Try to get the RGBA of the default texture entry.. 305 if (part == null)
305 // 306 continue;
306 try 307
308 // Draw if the object is at least 1 meter wide in any direction
309 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f)
307 { 310 {
308 // get the null checks out of the way 311 // Try to get the RGBA of the default texture entry..
309 // skip the ones that break 312 //
310 if (part == null) 313 try
311 continue; 314 {
315 // get the null checks out of the way
316 // skip the ones that break
317 if (part == null)
318 continue;
312 319
313 if (part.Shape == null) 320 if (part.Shape == null)
314 continue; 321 continue;
315 322
316 if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass) 323 if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass)
317 continue; // eliminates trees from this since we don't really have a good tree representation 324 continue; // eliminates trees from this since we don't really have a good tree representation
318 // if you want tree blocks on the map comment the above line and uncomment the below line 325 // if you want tree blocks on the map comment the above line and uncomment the below line
319 //mapdotspot = Color.PaleGreen; 326 //mapdotspot = Color.PaleGreen;
320 327
321 Primitive.TextureEntry textureEntry = part.Shape.Textures; 328 Primitive.TextureEntry textureEntry = part.Shape.Textures;
322 329
323 if (textureEntry == null || textureEntry.DefaultTexture == null) 330 if (textureEntry == null || textureEntry.DefaultTexture == null)
324 continue; 331 continue;
325 332
326 Color4 texcolor = textureEntry.DefaultTexture.RGBA; 333 Color4 texcolor = textureEntry.DefaultTexture.RGBA;
327 334
328 // Not sure why some of these are null, oh well. 335 // Not sure why some of these are null, oh well.
329 336
330 int colorr = 255 - (int)(texcolor.R * 255f); 337 int colorr = 255 - (int)(texcolor.R * 255f);
331 int colorg = 255 - (int)(texcolor.G * 255f); 338 int colorg = 255 - (int)(texcolor.G * 255f);
332 int colorb = 255 - (int)(texcolor.B * 255f); 339 int colorb = 255 - (int)(texcolor.B * 255f);
333 340
334 if (!(colorr == 255 && colorg == 255 && colorb == 255)) 341 if (!(colorr == 255 && colorg == 255 && colorb == 255))
335 {
336 //Try to set the map spot color
337 try
338 {
339 // If the color gets goofy somehow, skip it *shakes fist at Color4
340 mapdotspot = Color.FromArgb(colorr, colorg, colorb);
341 }
342 catch (ArgumentException)
343 { 342 {
343 //Try to set the map spot color
344 try
345 {
346 // If the color gets goofy somehow, skip it *shakes fist at Color4
347 mapdotspot = Color.FromArgb(colorr, colorg, colorb);
348 }
349 catch (ArgumentException)
350 {
351 }
344 } 352 }
345 } 353 }
346 } 354 catch (IndexOutOfRangeException)
347 catch (IndexOutOfRangeException) 355 {
348 { 356 // Windows Array
349 // Windows Array 357 }
350 } 358 catch (ArgumentOutOfRangeException)
351 catch (ArgumentOutOfRangeException) 359 {
352 { 360 // Mono Array
353 // Mono Array 361 }
354 }
355
356 Vector3 pos = part.GetWorldPosition();
357
358 // skip prim outside of retion
359 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
360 continue;
361
362 // skip prim in non-finite position
363 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
364 Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
365 continue;
366
367 // Figure out if object is under 256m above the height of the terrain
368 bool isBelow256AboveTerrain = false;
369 362
370 try 363 Vector3 pos = part.GetWorldPosition();
371 {
372 isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
373 }
374 catch (Exception)
375 {
376 }
377 364
378 if (isBelow256AboveTerrain) 365 // skip prim outside of retion
379 { 366 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
380 // Translate scale by rotation so scale is represented properly when object is rotated
381 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
382 Vector3 scale = new Vector3();
383 Vector3 tScale = new Vector3();
384 Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
385
386 Quaternion llrot = part.GetWorldRotation();
387 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
388 scale = lscale * rot;
389
390 // negative scales don't work in this situation
391 scale.X = Math.Abs(scale.X);
392 scale.Y = Math.Abs(scale.Y);
393 scale.Z = Math.Abs(scale.Z);
394
395 // This scaling isn't very accurate and doesn't take into account the face rotation :P
396 int mapdrawstartX = (int)(pos.X - scale.X);
397 int mapdrawstartY = (int)(pos.Y - scale.Y);
398 int mapdrawendX = (int)(pos.X + scale.X);
399 int mapdrawendY = (int)(pos.Y + scale.Y);
400
401 // If object is beyond the edge of the map, don't draw it to avoid errors
402 if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
403 || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
404 || mapdrawendY > ((int)Constants.RegionSize - 1))
405 continue; 367 continue;
406 368
407#region obb face reconstruction part duex 369 // skip prim in non-finite position
408 Vector3[] vertexes = new Vector3[8]; 370 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
409 371 Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
410 // float[] distance = new float[6]; 372 continue;
411 Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
412 Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
413 Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
414 Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
415
416 tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
417 scale = ((tScale * rot));
418 vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
419 // vertexes[0].x = pos.X + vertexes[0].x;
420 //vertexes[0].y = pos.Y + vertexes[0].y;
421 //vertexes[0].z = pos.Z + vertexes[0].z;
422
423 FaceA[0] = vertexes[0];
424 FaceB[3] = vertexes[0];
425 FaceA[4] = vertexes[0];
426
427 tScale = lscale;
428 scale = ((tScale * rot));
429 vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
430
431 // vertexes[1].x = pos.X + vertexes[1].x;
432 // vertexes[1].y = pos.Y + vertexes[1].y;
433 //vertexes[1].z = pos.Z + vertexes[1].z;
434
435 FaceB[0] = vertexes[1];
436 FaceA[1] = vertexes[1];
437 FaceC[4] = vertexes[1];
438
439 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
440 scale = ((tScale * rot));
441
442 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
443
444 //vertexes[2].x = pos.X + vertexes[2].x;
445 //vertexes[2].y = pos.Y + vertexes[2].y;
446 //vertexes[2].z = pos.Z + vertexes[2].z;
447
448 FaceC[0] = vertexes[2];
449 FaceD[3] = vertexes[2];
450 FaceC[5] = vertexes[2];
451
452 tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
453 scale = ((tScale * rot));
454 vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
455
456 //vertexes[3].x = pos.X + vertexes[3].x;
457 // vertexes[3].y = pos.Y + vertexes[3].y;
458 // vertexes[3].z = pos.Z + vertexes[3].z;
459
460 FaceD[0] = vertexes[3];
461 FaceC[1] = vertexes[3];
462 FaceA[5] = vertexes[3];
463
464 tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
465 scale = ((tScale * rot));
466 vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
467
468 // vertexes[4].x = pos.X + vertexes[4].x;
469 // vertexes[4].y = pos.Y + vertexes[4].y;
470 // vertexes[4].z = pos.Z + vertexes[4].z;
471
472 FaceB[1] = vertexes[4];
473 FaceA[2] = vertexes[4];
474 FaceD[4] = vertexes[4];
475
476 tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
477 scale = ((tScale * rot));
478 vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
479
480 // vertexes[5].x = pos.X + vertexes[5].x;
481 // vertexes[5].y = pos.Y + vertexes[5].y;
482 // vertexes[5].z = pos.Z + vertexes[5].z;
483
484 FaceD[1] = vertexes[5];
485 FaceC[2] = vertexes[5];
486 FaceB[5] = vertexes[5];
487 373
488 tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z); 374 // Figure out if object is under 256m above the height of the terrain
489 scale = ((tScale * rot)); 375 bool isBelow256AboveTerrain = false;
490 vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
491 376
492 // vertexes[6].x = pos.X + vertexes[6].x; 377 try
493 // vertexes[6].y = pos.Y + vertexes[6].y; 378 {
494 // vertexes[6].z = pos.Z + vertexes[6].z; 379 isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
380 }
381 catch (Exception)
382 {
383 }
495 384
496 FaceB[2] = vertexes[6]; 385 if (isBelow256AboveTerrain)
497 FaceA[3] = vertexes[6]; 386 {
498 FaceB[4] = vertexes[6]; 387 // Translate scale by rotation so scale is represented properly when object is rotated
388 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
389 Vector3 scale = new Vector3();
390 Vector3 tScale = new Vector3();
391 Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
392
393 Quaternion llrot = part.GetWorldRotation();
394 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
395 scale = lscale * rot;
396
397 // negative scales don't work in this situation
398 scale.X = Math.Abs(scale.X);
399 scale.Y = Math.Abs(scale.Y);
400 scale.Z = Math.Abs(scale.Z);
401
402 // This scaling isn't very accurate and doesn't take into account the face rotation :P
403 int mapdrawstartX = (int)(pos.X - scale.X);
404 int mapdrawstartY = (int)(pos.Y - scale.Y);
405 int mapdrawendX = (int)(pos.X + scale.X);
406 int mapdrawendY = (int)(pos.Y + scale.Y);
407
408 // If object is beyond the edge of the map, don't draw it to avoid errors
409 if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
410 || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
411 || mapdrawendY > ((int)Constants.RegionSize - 1))
412 continue;
413
414 #region obb face reconstruction part duex
415 Vector3[] vertexes = new Vector3[8];
416
417 // float[] distance = new float[6];
418 Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
419 Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
420 Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
421 Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
422
423 tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
424 scale = ((tScale * rot));
425 vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
426 // vertexes[0].x = pos.X + vertexes[0].x;
427 //vertexes[0].y = pos.Y + vertexes[0].y;
428 //vertexes[0].z = pos.Z + vertexes[0].z;
429
430 FaceA[0] = vertexes[0];
431 FaceB[3] = vertexes[0];
432 FaceA[4] = vertexes[0];
433
434 tScale = lscale;
435 scale = ((tScale * rot));
436 vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
437
438 // vertexes[1].x = pos.X + vertexes[1].x;
439 // vertexes[1].y = pos.Y + vertexes[1].y;
440 //vertexes[1].z = pos.Z + vertexes[1].z;
441
442 FaceB[0] = vertexes[1];
443 FaceA[1] = vertexes[1];
444 FaceC[4] = vertexes[1];
445
446 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
447 scale = ((tScale * rot));
448
449 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
450
451 //vertexes[2].x = pos.X + vertexes[2].x;
452 //vertexes[2].y = pos.Y + vertexes[2].y;
453 //vertexes[2].z = pos.Z + vertexes[2].z;
454
455 FaceC[0] = vertexes[2];
456 FaceD[3] = vertexes[2];
457 FaceC[5] = vertexes[2];
458
459 tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
460 scale = ((tScale * rot));
461 vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
462
463 //vertexes[3].x = pos.X + vertexes[3].x;
464 // vertexes[3].y = pos.Y + vertexes[3].y;
465 // vertexes[3].z = pos.Z + vertexes[3].z;
466
467 FaceD[0] = vertexes[3];
468 FaceC[1] = vertexes[3];
469 FaceA[5] = vertexes[3];
470
471 tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
472 scale = ((tScale * rot));
473 vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
474
475 // vertexes[4].x = pos.X + vertexes[4].x;
476 // vertexes[4].y = pos.Y + vertexes[4].y;
477 // vertexes[4].z = pos.Z + vertexes[4].z;
478
479 FaceB[1] = vertexes[4];
480 FaceA[2] = vertexes[4];
481 FaceD[4] = vertexes[4];
482
483 tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
484 scale = ((tScale * rot));
485 vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
486
487 // vertexes[5].x = pos.X + vertexes[5].x;
488 // vertexes[5].y = pos.Y + vertexes[5].y;
489 // vertexes[5].z = pos.Z + vertexes[5].z;
490
491 FaceD[1] = vertexes[5];
492 FaceC[2] = vertexes[5];
493 FaceB[5] = vertexes[5];
494
495 tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z);
496 scale = ((tScale * rot));
497 vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
498
499 // vertexes[6].x = pos.X + vertexes[6].x;
500 // vertexes[6].y = pos.Y + vertexes[6].y;
501 // vertexes[6].z = pos.Z + vertexes[6].z;
502
503 FaceB[2] = vertexes[6];
504 FaceA[3] = vertexes[6];
505 FaceB[4] = vertexes[6];
499 506
500 tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z); 507 tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z);
501 scale = ((tScale * rot)); 508 scale = ((tScale * rot));
502 vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); 509 vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
503 510
504 // vertexes[7].x = pos.X + vertexes[7].x; 511 // vertexes[7].x = pos.X + vertexes[7].x;
505 // vertexes[7].y = pos.Y + vertexes[7].y; 512 // vertexes[7].y = pos.Y + vertexes[7].y;
506 // vertexes[7].z = pos.Z + vertexes[7].z; 513 // vertexes[7].z = pos.Z + vertexes[7].z;
507 514
508 FaceD[2] = vertexes[7]; 515 FaceD[2] = vertexes[7];
509 FaceC[3] = vertexes[7]; 516 FaceC[3] = vertexes[7];
510 FaceD[5] = vertexes[7]; 517 FaceD[5] = vertexes[7];
511#endregion 518 #endregion
512 519
513 //int wy = 0; 520 //int wy = 0;
514 521
515 //bool breakYN = false; // If we run into an error drawing, break out of the 522 //bool breakYN = false; // If we run into an error drawing, break out of the
516 // loop so we don't lag to death on error handling 523 // loop so we don't lag to death on error handling
517 DrawStruct ds = new DrawStruct(); 524 DrawStruct ds = new DrawStruct();
518 ds.brush = new SolidBrush(mapdotspot); 525 ds.brush = new SolidBrush(mapdotspot);
519 //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY); 526 //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY);
520 527
521 ds.trns = new face[FaceA.Length]; 528 ds.trns = new face[FaceA.Length];
522 529
523 for (int i = 0; i < FaceA.Length; i++) 530 for (int i = 0; i < FaceA.Length; i++)
524 { 531 {
525 Point[] working = new Point[5]; 532 Point[] working = new Point[5];
526 working[0] = project(FaceA[i], axPos); 533 working[0] = project(FaceA[i], axPos);
527 working[1] = project(FaceB[i], axPos); 534 working[1] = project(FaceB[i], axPos);
528 working[2] = project(FaceD[i], axPos); 535 working[2] = project(FaceD[i], axPos);
529 working[3] = project(FaceC[i], axPos); 536 working[3] = project(FaceC[i], axPos);
530 working[4] = project(FaceA[i], axPos); 537 working[4] = project(FaceA[i], axPos);
531 538
532 face workingface = new face(); 539 face workingface = new face();
533 workingface.pts = working; 540 workingface.pts = working;
534 541
535 ds.trns[i] = workingface; 542 ds.trns[i] = workingface;
536 } 543 }
537 544
538 z_sort.Add(part.LocalId, ds); 545 z_sort.Add(part.LocalId, ds);
539 z_localIDs.Add(part.LocalId); 546 z_localIDs.Add(part.LocalId);
540 z_sortheights.Add(pos.Z); 547 z_sortheights.Add(pos.Z);
541 548
542 //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) 549 //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++)
543 //{
544 //for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
545 //{ 550 //{
546 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy); 551 //for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
547 //try
548 //{
549 // Remember, flip the y!
550 // mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
551 //}
552 //catch (ArgumentException)
553 //{ 552 //{
554 // breakYN = true; 553 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy);
554 //try
555 //{
556 // Remember, flip the y!
557 // mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
558 //}
559 //catch (ArgumentException)
560 //{
561 // breakYN = true;
562 //}
563
564 //if (breakYN)
565 // break;
555 //} 566 //}
556 567
557 //if (breakYN) 568 //if (breakYN)
558 // break; 569 // break;
559 //} 570 //}
571 } // Object is within 256m Z of terrain
572 } // object is at least a meter wide
573 } // loop over group children
574 } // entitybase is sceneobject group
575 } // foreach loop over entities
560 576
561 //if (breakYN) 577 float[] sortedZHeights = z_sortheights.ToArray();
562 // break; 578 uint[] sortedlocalIds = z_localIDs.ToArray();
563 //}
564 } // Object is within 256m Z of terrain
565 } // object is at least a meter wide
566 } // loop over group children
567 } // entitybase is sceneobject group
568 } // foreach loop over entities
569
570 float[] sortedZHeights = z_sortheights.ToArray();
571 uint[] sortedlocalIds = z_localIDs.ToArray();
572
573 // Sort prim by Z position
574 Array.Sort(sortedZHeights, sortedlocalIds);
575 579
576 Graphics g = Graphics.FromImage(mapbmp); 580 // Sort prim by Z position
581 Array.Sort(sortedZHeights, sortedlocalIds);
577 582
578 for (int s = 0; s < sortedZHeights.Length; s++) 583 using (Graphics g = Graphics.FromImage(mapbmp))
579 {
580 if (z_sort.ContainsKey(sortedlocalIds[s]))
581 { 584 {
582 DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]]; 585 for (int s = 0; s < sortedZHeights.Length; s++)
583 for (int r = 0; r < rectDrawStruct.trns.Length; r++)
584 { 586 {
585 g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts); 587 if (z_sort.ContainsKey(sortedlocalIds[s]))
588 {
589 DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]];
590 for (int r = 0; r < rectDrawStruct.trns.Length; r++)
591 {
592 g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts);
593 }
594 //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect);
595 }
586 } 596 }
587 //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect);
588 } 597 }
589 } 598 } // lock entities objs
590 599
591 g.Dispose(); 600 }
592 } // lock entities objs 601 finally
602 {
603 foreach (DrawStruct ds in z_sort.Values)
604 ds.brush.Dispose();
605 }
593 606
594 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms"); 607 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms");
608
595 return mapbmp; 609 return mapbmp;
596 } 610 }
597 611
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
index 992bff3..cb06fd4 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
54 public void TerrainToBitmap(Bitmap mapbmp) 54 public void TerrainToBitmap(Bitmap mapbmp)
55 { 55 {
56 int tc = Environment.TickCount; 56 int tc = Environment.TickCount;
57 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); 57 m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
58 58
59 double[,] hm = m_scene.Heightmap.GetDoubles(); 59 double[,] hm = m_scene.Heightmap.GetDoubles();
60 bool ShadowDebugContinue = true; 60 bool ShadowDebugContinue = true;
@@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
199 { 199 {
200 if (!terraincorruptedwarningsaid) 200 if (!terraincorruptedwarningsaid)
201 { 201 {
202 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); 202 m_log.WarnFormat("[SHADED MAP TILE RENDERER]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
203 terraincorruptedwarningsaid = true; 203 terraincorruptedwarningsaid = true;
204 } 204 }
205 color = Color.Black; 205 color = Color.Black;
@@ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
229 { 229 {
230 if (!terraincorruptedwarningsaid) 230 if (!terraincorruptedwarningsaid)
231 { 231 {
232 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); 232 m_log.WarnFormat("[SHADED MAP TILE RENDERER]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
233 terraincorruptedwarningsaid = true; 233 terraincorruptedwarningsaid = true;
234 } 234 }
235 Color black = Color.Black; 235 Color black = Color.Black;
@@ -238,7 +238,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
238 } 238 }
239 } 239 }
240 } 240 }
241 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); 241
242 m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
242 } 243 }
243 } 244 }
244} 245} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
index d13c2ef..e895178 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
173 private Bitmap fetchTexture(UUID id) 173 private Bitmap fetchTexture(UUID id)
174 { 174 {
175 AssetBase asset = m_scene.AssetService.Get(id.ToString()); 175 AssetBase asset = m_scene.AssetService.Get(id.ToString());
176 m_log.DebugFormat("[TexturedMapTileRenderer]: Fetched texture {0}, found: {1}", id, asset != null); 176 m_log.DebugFormat("[TEXTURED MAP TILE RENDERER]: Fetched texture {0}, found: {1}", id, asset != null);
177 if (asset == null) return null; 177 if (asset == null) return null;
178 178
179 ManagedImage managedImage; 179 ManagedImage managedImage;
@@ -188,17 +188,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
188 } 188 }
189 catch (DllNotFoundException) 189 catch (DllNotFoundException)
190 { 190 {
191 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id); 191 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id);
192 192
193 } 193 }
194 catch (IndexOutOfRangeException) 194 catch (IndexOutOfRangeException)
195 { 195 {
196 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); 196 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id);
197 197
198 } 198 }
199 catch (Exception) 199 catch (Exception)
200 { 200 {
201 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); 201 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id);
202 202
203 } 203 }
204 return null; 204 return null;
@@ -233,10 +233,14 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
233 if (textureID == UUID.Zero) return defaultColor; // not set 233 if (textureID == UUID.Zero) return defaultColor; // not set
234 if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures 234 if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures
235 235
236 Bitmap bmp = fetchTexture(textureID); 236 Color color;
237 Color color = bmp == null ? defaultColor : computeAverageColor(bmp); 237
238 // store it for future reference 238 using (Bitmap bmp = fetchTexture(textureID))
239 m_mapping[textureID] = color; 239 {
240 color = bmp == null ? defaultColor : computeAverageColor(bmp);
241 // store it for future reference
242 m_mapping[textureID] = color;
243 }
240 244
241 return color; 245 return color;
242 } 246 }
@@ -278,7 +282,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
278 public void TerrainToBitmap(Bitmap mapbmp) 282 public void TerrainToBitmap(Bitmap mapbmp)
279 { 283 {
280 int tc = Environment.TickCount; 284 int tc = Environment.TickCount;
281 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); 285 m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
282 286
283 // These textures should be in the AssetCache anyway, as every client conneting to this 287 // These textures should be in the AssetCache anyway, as every client conneting to this
284 // region needs them. Except on start, when the map is recreated (before anyone connected), 288 // region needs them. Except on start, when the map is recreated (before anyone connected),
@@ -412,7 +416,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
412 } 416 }
413 } 417 }
414 } 418 }
415 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); 419
420 m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
416 } 421 }
417 } 422 }
418} 423} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 28daf2f..d4e4c25 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -205,13 +205,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
205 item.InvType = (int)InventoryType.Object; 205 item.InvType = (int)InventoryType.Object;
206 item.Folder = categoryID; 206 item.Folder = categoryID;
207 207
208 uint nextPerms=(perms & 7) << 13; 208 PermissionsUtil.ApplyFoldedPermissions(perms, ref perms);
209 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
210 perms &= ~(uint)PermissionMask.Copy;
211 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
212 perms &= ~(uint)PermissionMask.Transfer;
213 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
214 perms &= ~(uint)PermissionMask.Modify;
215 209
216 item.BasePermissions = perms & part.NextOwnerMask; 210 item.BasePermissions = perms & part.NextOwnerMask;
217 item.CurrentPermissions = perms & part.NextOwnerMask; 211 item.CurrentPermissions = perms & part.NextOwnerMask;
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index e434b2e..e77f0aa 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -546,7 +546,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
546 { 546 {
547 ConsoleDisplayList cdl = new ConsoleDisplayList(); 547 ConsoleDisplayList cdl = new ConsoleDisplayList();
548 cdl.AddRow("Name", so.Name); 548 cdl.AddRow("Name", so.Name);
549 cdl.AddRow("Descrition", so.Description); 549 cdl.AddRow("Description", so.Description);
550 cdl.AddRow("Local ID", so.LocalId); 550 cdl.AddRow("Local ID", so.LocalId);
551 cdl.AddRow("UUID", so.UUID); 551 cdl.AddRow("UUID", so.UUID);
552 cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name)); 552 cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name));
@@ -631,7 +631,22 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
631 cdl.AddRow("SculptType", s.SculptType); 631 cdl.AddRow("SculptType", s.SculptType);
632 cdl.AddRow("State", s.State); 632 cdl.AddRow("State", s.State);
633 633
634 // TODO, unpack and display texture entries 634 // TODO, need to display more information about textures but in a compact format
635 // to stop output becoming huge.
636 for (int i = 0; i < sop.GetNumberOfSides(); i++)
637 {
638 Primitive.TextureEntryFace teFace = s.Textures.FaceTextures[i];
639
640 UUID textureID;
641
642 if (teFace != null)
643 textureID = teFace.TextureID;
644 else
645 textureID = s.Textures.DefaultTexture.TextureID;
646
647 cdl.AddRow(string.Format("Face {0} texture ID", i), textureID);
648 }
649
635 //cdl.AddRow("Textures", string.Format("{0} entries", s.Textures. 650 //cdl.AddRow("Textures", string.Format("{0} entries", s.Textures.
636 } 651 }
637 652
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 4f5b9b7..616fe98 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -1453,6 +1453,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1453 1453
1454 bool permission = false; 1454 bool permission = false;
1455 1455
1456// m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name);
1457
1456 ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); 1458 ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
1457 if (land == null) return false; 1459 if (land == null) return false;
1458 1460
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 9c441ed..0c74b49 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -48,8 +48,8 @@ namespace OpenSim.Region.CoreModules.World.Region
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")]
49 public class RestartModule : INonSharedRegionModule, IRestartModule 49 public class RestartModule : INonSharedRegionModule, IRestartModule
50 { 50 {
51// private static readonly ILog m_log = 51 private static readonly ILog m_log =
52// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 protected Scene m_Scene; 54 protected Scene m_Scene;
55 protected Timer m_CountdownTimer = null; 55 protected Timer m_CountdownTimer = null;
@@ -223,11 +223,25 @@ namespace OpenSim.Region.CoreModules.World.Region
223 223
224 public void SetTimer(int intervalSeconds) 224 public void SetTimer(int intervalSeconds)
225 { 225 {
226 m_CountdownTimer = new Timer(); 226 if (intervalSeconds > 0)
227 m_CountdownTimer.AutoReset = false; 227 {
228 m_CountdownTimer.Interval = intervalSeconds * 1000; 228 m_CountdownTimer = new Timer();
229 m_CountdownTimer.Elapsed += OnTimer; 229 m_CountdownTimer.AutoReset = false;
230 m_CountdownTimer.Start(); 230 m_CountdownTimer.Interval = intervalSeconds * 1000;
231 m_CountdownTimer.Elapsed += OnTimer;
232 m_CountdownTimer.Start();
233 }
234 else if (m_CountdownTimer != null)
235 {
236 m_CountdownTimer.Stop();
237 m_CountdownTimer = null;
238 }
239 else
240 {
241 m_log.WarnFormat(
242 "[RESTART MODULE]: Tried to set restart timer to {0} in {1}, which is not a valid interval",
243 intervalSeconds, m_Scene.Name);
244 }
231 } 245 }
232 246
233 private void OnTimer(object source, ElapsedEventArgs e) 247 private void OnTimer(object source, ElapsedEventArgs e)
@@ -332,4 +346,4 @@ namespace OpenSim.Region.CoreModules.World.Region
332 } 346 }
333 } 347 }
334 } 348 }
335} \ No newline at end of file 349}
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
index b4348c9..66059fb 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
@@ -144,7 +144,20 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
144 <Flags>None</Flags> 144 <Flags>None</Flags>
145 <CollisionSound><Guid>00000000-0000-0000-0000-000000000000</Guid></CollisionSound> 145 <CollisionSound><Guid>00000000-0000-0000-0000-000000000000</Guid></CollisionSound>
146 <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> 147 <DynAttrs>
148 <llsd>
149 <map>
150 <key>MyNamespace</key>
151 <map>
152 <key>MyStore</key>
153 <map>
154 <key>the answer</key>
155 <integer>42</integer>
156 </map>
157 </map>
158 </map>
159 </llsd>
160 </DynAttrs>
148 </SceneObjectPart> 161 </SceneObjectPart>
149 </RootPart> 162 </RootPart>
150 <OtherParts /> 163 <OtherParts />
@@ -333,7 +346,20 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
333 <EveryoneMask>0</EveryoneMask> 346 <EveryoneMask>0</EveryoneMask>
334 <NextOwnerMask>2147483647</NextOwnerMask> 347 <NextOwnerMask>2147483647</NextOwnerMask>
335 <Flags>None</Flags> 348 <Flags>None</Flags>
336 <DynAttrs><llsd><map><key>MyStore</key><map><key>last words</key><string>Rosebud</string></map></map></llsd></DynAttrs> 349 <DynAttrs>
350 <llsd>
351 <map>
352 <key>MyNamespace</key>
353 <map>
354 <key>MyStore</key>
355 <map>
356 <key>last words</key>
357 <string>Rosebud</string>
358 </map>
359 </map>
360 </map>
361 </llsd>
362 </DynAttrs>
337 <SitTargetAvatar><UUID>00000000-0000-0000-0000-000000000000</UUID></SitTargetAvatar> 363 <SitTargetAvatar><UUID>00000000-0000-0000-0000-000000000000</UUID></SitTargetAvatar>
338 </SceneObjectPart> 364 </SceneObjectPart>
339 <OtherParts /> 365 <OtherParts />
@@ -362,7 +388,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
362 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); 388 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790")));
363 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); 389 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d")));
364 Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide")); 390 Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide"));
365 OSDMap store = rootPart.DynAttrs["MyStore"]; 391 OSDMap store = rootPart.DynAttrs.GetStore("MyNamespace", "MyStore");
366 Assert.AreEqual(42, store["the answer"].AsInteger()); 392 Assert.AreEqual(42, store["the answer"].AsInteger());
367 393
368 // TODO: Check other properties 394 // TODO: Check other properties
@@ -414,13 +440,14 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
414 rp.CreatorID = rpCreatorId; 440 rp.CreatorID = rpCreatorId;
415 rp.Shape = shape; 441 rp.Shape = shape;
416 442
443 string daNamespace = "MyNamespace";
417 string daStoreName = "MyStore"; 444 string daStoreName = "MyStore";
418 string daKey = "foo"; 445 string daKey = "foo";
419 string daValue = "bar"; 446 string daValue = "bar";
420 OSDMap myStore = new OSDMap(); 447 OSDMap myStore = new OSDMap();
421 myStore.Add(daKey, daValue); 448 myStore.Add(daKey, daValue);
422 rp.DynAttrs = new DAMap(); 449 rp.DynAttrs = new DAMap();
423 rp.DynAttrs[daStoreName] = myStore; 450 rp.DynAttrs.SetStore(daNamespace, daStoreName, myStore);
424 451
425 SceneObjectGroup so = new SceneObjectGroup(rp); 452 SceneObjectGroup so = new SceneObjectGroup(rp);
426 453
@@ -481,7 +508,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
481 Assert.That(name, Is.EqualTo(rpName)); 508 Assert.That(name, Is.EqualTo(rpName));
482 Assert.That(creatorId, Is.EqualTo(rpCreatorId)); 509 Assert.That(creatorId, Is.EqualTo(rpCreatorId));
483 Assert.NotNull(daMap); 510 Assert.NotNull(daMap);
484 Assert.AreEqual(daValue, daMap[daStoreName][daKey].AsString()); 511 Assert.AreEqual(daValue, daMap.GetStore(daNamespace, daStoreName)[daKey].AsString());
485 } 512 }
486 513
487 [Test] 514 [Test]
@@ -496,7 +523,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
496 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946"))); 523 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946")));
497 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef"))); 524 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef")));
498 Assert.That(rootPart.Name, Is.EqualTo("PrimFun")); 525 Assert.That(rootPart.Name, Is.EqualTo("PrimFun"));
499 OSDMap store = rootPart.DynAttrs["MyStore"]; 526 OSDMap store = rootPart.DynAttrs.GetStore("MyNamespace", "MyStore");
500 Assert.AreEqual("Rosebud", store["last words"].AsString()); 527 Assert.AreEqual("Rosebud", store["last words"].AsString());
501 528
502 // TODO: Check other properties 529 // TODO: Check other properties
@@ -522,13 +549,14 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
522 rp.CreatorID = rpCreatorId; 549 rp.CreatorID = rpCreatorId;
523 rp.Shape = shape; 550 rp.Shape = shape;
524 551
552 string daNamespace = "MyNamespace";
525 string daStoreName = "MyStore"; 553 string daStoreName = "MyStore";
526 string daKey = "foo"; 554 string daKey = "foo";
527 string daValue = "bar"; 555 string daValue = "bar";
528 OSDMap myStore = new OSDMap(); 556 OSDMap myStore = new OSDMap();
529 myStore.Add(daKey, daValue); 557 myStore.Add(daKey, daValue);
530 rp.DynAttrs = new DAMap(); 558 rp.DynAttrs = new DAMap();
531 rp.DynAttrs[daStoreName] = myStore; 559 rp.DynAttrs.SetStore(daNamespace, daStoreName, myStore);
532 560
533 SceneObjectGroup so = new SceneObjectGroup(rp); 561 SceneObjectGroup so = new SceneObjectGroup(rp);
534 562
@@ -585,7 +613,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
585 Assert.That(name, Is.EqualTo(rpName)); 613 Assert.That(name, Is.EqualTo(rpName));
586 Assert.That(creatorId, Is.EqualTo(rpCreatorId)); 614 Assert.That(creatorId, Is.EqualTo(rpCreatorId));
587 Assert.NotNull(daMap); 615 Assert.NotNull(daMap);
588 Assert.AreEqual(daValue, daMap[daStoreName][daKey].AsString()); 616 Assert.AreEqual(daValue, daMap.GetStore(daNamespace, daStoreName)[daKey].AsString());
589 } 617 }
590 } 618 }
591} \ No newline at end of file 619} \ 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 883045a..d093224 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -369,6 +369,15 @@ namespace OpenSim.Region.CoreModules.World.Sound
369 }); 369 });
370 } 370 }
371 371
372 public void SetSoundQueueing(UUID objectID, bool shouldQueue)
373 {
374 SceneObjectPart part;
375 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
376 return;
377
378 part.SoundQueueing = shouldQueue;
379 }
380
372 #endregion 381 #endregion
373 } 382 }
374} 383}
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
index 9de588c..35014f5 100644
--- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
@@ -216,13 +216,13 @@ namespace OpenSim.Region.CoreModules
216 // FIXME: If console region is root then this will be printed by every module. Currently, there is no 216 // FIXME: If console region is root then this will be printed by every module. Currently, there is no
217 // way to prevent this, short of making the entire module shared (which is complete overkill). 217 // way to prevent this, short of making the entire module shared (which is complete overkill).
218 // One possibility is to return a bool to signal whether the module has completely handled the command 218 // One possibility is to return a bool to signal whether the module has completely handled the command
219 m_log.InfoFormat("[WIND]: Please change to a specific region in order to set Sun parameters."); 219 MainConsole.Instance.Output("Please change to a specific region in order to set Sun parameters.");
220 return; 220 return;
221 } 221 }
222 222
223 if (m_scene.ConsoleScene() != m_scene) 223 if (m_scene.ConsoleScene() != m_scene)
224 { 224 {
225 m_log.InfoFormat("[WIND]: Console Scene is not my scene."); 225 MainConsole.Instance.Output("Console Scene is not my scene.");
226 return; 226 return;
227 } 227 }
228 } 228 }
@@ -233,7 +233,9 @@ namespace OpenSim.Region.CoreModules
233 private void HandleConsoleCommand(string module, string[] cmdparams) 233 private void HandleConsoleCommand(string module, string[] cmdparams)
234 { 234 {
235 ValidateConsole(); 235 ValidateConsole();
236 m_log.Info("[WIND] The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins."); 236
237 MainConsole.Instance.Output(
238 "The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins.");
237 } 239 }
238 240
239 /// <summary> 241 /// <summary>
@@ -246,7 +248,9 @@ namespace OpenSim.Region.CoreModules
246 if ((cmdparams.Length != 4) 248 if ((cmdparams.Length != 4)
247 || !cmdparams[1].Equals("base")) 249 || !cmdparams[1].Equals("base"))
248 { 250 {
249 m_log.Info("[WIND] Invalid parameters to change parameters for Wind module base, usage: wind base <parameter> <value>"); 251 MainConsole.Instance.Output(
252 "Invalid parameters to change parameters for Wind module base, usage: wind base <parameter> <value>");
253
250 return; 254 return;
251 } 255 }
252 256
@@ -261,7 +265,9 @@ namespace OpenSim.Region.CoreModules
261 } 265 }
262 else 266 else
263 { 267 {
264 m_log.InfoFormat("[WIND] Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]); 268 MainConsole.Instance.OutputFormat(
269 "Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]);
270
265 return; 271 return;
266 } 272 }
267 273
@@ -271,22 +277,23 @@ namespace OpenSim.Region.CoreModules
271 277
272 if (desiredPlugin.Equals(m_activeWindPlugin.Name)) 278 if (desiredPlugin.Equals(m_activeWindPlugin.Name))
273 { 279 {
274 m_log.InfoFormat("[WIND] Wind model plugin {0} is already active", cmdparams[3]); 280 MainConsole.Instance.OutputFormat("Wind model plugin {0} is already active", cmdparams[3]);
281
275 return; 282 return;
276 } 283 }
277 284
278 if (m_availableWindPlugins.ContainsKey(desiredPlugin)) 285 if (m_availableWindPlugins.ContainsKey(desiredPlugin))
279 { 286 {
280 m_activeWindPlugin = m_availableWindPlugins[cmdparams[3]]; 287 m_activeWindPlugin = m_availableWindPlugins[cmdparams[3]];
281 m_log.InfoFormat("[WIND] {0} wind model plugin now active", m_activeWindPlugin.Name); 288
289 MainConsole.Instance.OutputFormat("{0} wind model plugin now active", m_activeWindPlugin.Name);
282 } 290 }
283 else 291 else
284 { 292 {
285 m_log.InfoFormat("[WIND] Could not find wind model plugin {0}", desiredPlugin); 293 MainConsole.Instance.OutputFormat("Could not find wind model plugin {0}", desiredPlugin);
286 } 294 }
287 break; 295 break;
288 } 296 }
289
290 } 297 }
291 298
292 /// <summary> 299 /// <summary>
@@ -300,7 +307,7 @@ namespace OpenSim.Region.CoreModules
300 if ((cmdparams.Length != 4) 307 if ((cmdparams.Length != 4)
301 && (cmdparams.Length != 3)) 308 && (cmdparams.Length != 3))
302 { 309 {
303 m_log.Info("[WIND] Usage: wind <plugin> <param> [value]"); 310 MainConsole.Instance.Output("Usage: wind <plugin> <param> [value]");
304 return; 311 return;
305 } 312 }
306 313
@@ -311,16 +318,17 @@ namespace OpenSim.Region.CoreModules
311 { 318 {
312 if (!float.TryParse(cmdparams[3], out value)) 319 if (!float.TryParse(cmdparams[3], out value))
313 { 320 {
314 m_log.InfoFormat("[WIND] Invalid value {0}", cmdparams[3]); 321 MainConsole.Instance.OutputFormat("Invalid value {0}", cmdparams[3]);
315 } 322 }
316 323
317 try 324 try
318 { 325 {
319 WindParamSet(plugin, param, value); 326 WindParamSet(plugin, param, value);
327 MainConsole.Instance.OutputFormat("{0} set to {1}", param, value);
320 } 328 }
321 catch (Exception e) 329 catch (Exception e)
322 { 330 {
323 m_log.InfoFormat("[WIND] {0}", e.Message); 331 MainConsole.Instance.OutputFormat("{0}", e.Message);
324 } 332 }
325 } 333 }
326 else 334 else
@@ -328,11 +336,11 @@ namespace OpenSim.Region.CoreModules
328 try 336 try
329 { 337 {
330 value = WindParamGet(plugin, param); 338 value = WindParamGet(plugin, param);
331 m_log.InfoFormat("[WIND] {0} : {1}", param, value); 339 MainConsole.Instance.OutputFormat("{0} : {1}", param, value);
332 } 340 }
333 catch (Exception e) 341 catch (Exception e)
334 { 342 {
335 m_log.InfoFormat("[WIND] {0}", e.Message); 343 MainConsole.Instance.OutputFormat("{0}", e.Message);
336 } 344 }
337 } 345 }
338 346
@@ -366,13 +374,11 @@ namespace OpenSim.Region.CoreModules
366 { 374 {
367 IWindModelPlugin windPlugin = m_availableWindPlugins[plugin]; 375 IWindModelPlugin windPlugin = m_availableWindPlugins[plugin];
368 windPlugin.WindParamSet(param, value); 376 windPlugin.WindParamSet(param, value);
369 m_log.InfoFormat("[WIND] {0} set to {1}", param, value);
370 } 377 }
371 else 378 else
372 { 379 {
373 throw new Exception(String.Format("Could not find plugin {0}", plugin)); 380 throw new Exception(String.Format("Could not find plugin {0}", plugin));
374 } 381 }
375
376 } 382 }
377 383
378 public float WindParamGet(string plugin, string param) 384 public float WindParamGet(string plugin, string param)
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index bf18616..5412359 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -115,6 +115,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
115 "export-map [<path>]", 115 "export-map [<path>]",
116 "Save an image of the world map", HandleExportWorldMapConsoleCommand); 116 "Save an image of the world map", HandleExportWorldMapConsoleCommand);
117 117
118 m_scene.AddCommand(
119 "Regions", this, "generate map",
120 "generate map",
121 "Generates and stores a new maptile.", HandleGenerateMapConsoleCommand);
122
118 AddHandlers(); 123 AddHandlers();
119 } 124 }
120 } 125 }
@@ -162,7 +167,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
162 regionimage = regionimage.Replace("-", ""); 167 regionimage = regionimage.Replace("-", "");
163 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage); 168 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage);
164 169
165 MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage); 170 MainServer.Instance.AddHTTPHandler(regionimage,
171 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions()
172 {
173 AllowXForwardedFor = false,
174 ForgetTimeSpan = TimeSpan.FromMinutes(2),
175 MaxRequestsInTimeframe = 4,
176 ReportingName = "MAPDOSPROTECTOR",
177 RequestTimeSpan = TimeSpan.FromSeconds(10),
178 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
179 }).Process);
166 MainServer.Instance.AddLLSDHandler( 180 MainServer.Instance.AddLLSDHandler(
167 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); 181 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest);
168 182
@@ -1131,6 +1145,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1131 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize); 1145 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1132 } 1146 }
1133 1147
1148 public Hashtable OnHTTPThrottled(Hashtable keysvals)
1149 {
1150 Hashtable reply = new Hashtable();
1151 int statuscode = 500;
1152 reply["str_response_string"] = "";
1153 reply["int_response_code"] = statuscode;
1154 reply["content_type"] = "text/plain";
1155 return reply;
1156 }
1157
1134 public Hashtable OnHTTPGetMapImage(Hashtable keysvals) 1158 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
1135 { 1159 {
1136 m_log.Debug("[WORLD MAP]: Sending map image jpeg"); 1160 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
@@ -1305,6 +1329,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1305 m_scene.RegionInfo.RegionName, exportPath); 1329 m_scene.RegionInfo.RegionName, exportPath);
1306 } 1330 }
1307 1331
1332 public void HandleGenerateMapConsoleCommand(string module, string[] cmdparams)
1333 {
1334 Scene consoleScene = m_scene.ConsoleScene();
1335
1336 if (consoleScene != null && consoleScene != m_scene)
1337 return;
1338
1339 GenerateMaptile();
1340 }
1341
1308 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) 1342 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
1309 { 1343 {
1310 uint xstart = 0; 1344 uint xstart = 0;
@@ -1542,88 +1576,69 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1542 1576
1543 private Byte[] GenerateOverlay() 1577 private Byte[] GenerateOverlay()
1544 { 1578 {
1545 Bitmap overlay = new Bitmap(256, 256); 1579 using (Bitmap overlay = new Bitmap(256, 256))
1546
1547 bool[,] saleBitmap = new bool[64, 64];
1548 for (int x = 0 ; x < 64 ; x++)
1549 { 1580 {
1550 for (int y = 0 ; y < 64 ; y++) 1581 bool[,] saleBitmap = new bool[64, 64];
1551 saleBitmap[x, y] = false; 1582 for (int x = 0 ; x < 64 ; x++)
1552 } 1583 {
1553 1584 for (int y = 0 ; y < 64 ; y++)
1554 bool landForSale = false; 1585 saleBitmap[x, y] = false;
1586 }
1555 1587
1556 List<ILandObject> parcels = m_scene.LandChannel.AllParcels(); 1588 bool landForSale = false;
1557 1589
1558 Color background = Color.FromArgb(0, 0, 0, 0); 1590 List<ILandObject> parcels = m_scene.LandChannel.AllParcels();
1559 SolidBrush transparent = new SolidBrush(background);
1560 Graphics g = Graphics.FromImage(overlay);
1561 g.FillRectangle(transparent, 0, 0, 255, 255);
1562 1591
1563 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)); 1592 Color background = Color.FromArgb(0, 0, 0, 0);
1564 Pen grey = new Pen(Color.FromArgb(255, 92, 92, 92));
1565 1593
1566 foreach (ILandObject land in parcels) 1594 using (Graphics g = Graphics.FromImage(overlay))
1567 {
1568 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags);
1569 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1570 { 1595 {
1571 landForSale = true; 1596 using (SolidBrush transparent = new SolidBrush(background))
1572 1597 g.FillRectangle(transparent, 0, 0, 256, 256);
1573 bool[,] landBitmap = land.GetLandBitmap();
1574 1598
1575 for (int x = 0 ; x < 64 ; x++) 1599
1600 foreach (ILandObject land in parcels)
1576 { 1601 {
1577 for (int y = 0 ; y < 64 ; y++) 1602 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags);
1603 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1578 { 1604 {
1579 if (landBitmap[x, y]) 1605 landForSale = true;
1606
1607 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap());
1608 }
1609 }
1610
1611 if (!landForSale)
1612 {
1613 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
1614 return null;
1615 }
1616
1617 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1618
1619 using (SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)))
1620 {
1621 for (int x = 0 ; x < 64 ; x++)
1622 {
1623 for (int y = 0 ; y < 64 ; y++)
1580 { 1624 {
1581 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4); 1625 if (saleBitmap[x, y])
1582 1626 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1583 if (x > 0)
1584 {
1585 if ((saleBitmap[x - 1, y] || landBitmap[x - 1, y]) == false)
1586 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4, 255 - (y * 4));
1587 }
1588 if (y > 0)
1589 {
1590 if ((saleBitmap[x, y-1] || landBitmap[x, y-1]) == false)
1591 g.DrawLine(grey, x * 4, 255 - (y * 4), x * 4 + 3, 255 - (y * 4));
1592 }
1593 if (x < 63)
1594 {
1595 if ((saleBitmap[x + 1, y] || landBitmap[x + 1, y]) == false)
1596 g.DrawLine(grey, x * 4 + 3, 252 - (y * 4), x * 4 + 3, 255 - (y * 4));
1597 }
1598 if (y < 63)
1599 {
1600 if ((saleBitmap[x, y + 1] || landBitmap[x, y + 1]) == false)
1601 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4 + 3, 252 - (y * 4));
1602 }
1603 } 1627 }
1604 } 1628 }
1605 } 1629 }
1606
1607 saleBitmap = land.MergeLandBitmaps(saleBitmap, landBitmap);
1608 } 1630 }
1609 }
1610 1631
1611 if (!landForSale) 1632 try
1612 { 1633 {
1613 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName); 1634 return OpenJPEG.EncodeFromImage(overlay, true);
1614 return null; 1635 }
1636 catch (Exception e)
1637 {
1638 m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString());
1639 }
1615 } 1640 }
1616 1641
1617 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1618
1619 try
1620 {
1621 return OpenJPEG.EncodeFromImage(overlay, true);
1622 }
1623 catch (Exception e)
1624 {
1625 m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString());
1626 }
1627 return null; 1642 return null;
1628 } 1643 }
1629 } 1644 }
diff --git a/OpenSim/Region/DataSnapshot/DataRequestHandler.cs b/OpenSim/Region/DataSnapshot/DataRequestHandler.cs
index 32e93b4..50276ae 100644
--- a/OpenSim/Region/DataSnapshot/DataRequestHandler.cs
+++ b/OpenSim/Region/DataSnapshot/DataRequestHandler.cs
@@ -63,7 +63,7 @@ namespace OpenSim.Region.DataSnapshot
63 63
64 public Hashtable OnGetSnapshot(Hashtable keysvals) 64 public Hashtable OnGetSnapshot(Hashtable keysvals)
65 { 65 {
66 m_log.Info("[DATASNAPSHOT] Received collection request"); 66 m_log.Debug("[DATASNAPSHOT] Received collection request");
67 Hashtable reply = new Hashtable(); 67 Hashtable reply = new Hashtable();
68 int statuscode = 200; 68 int statuscode = 200;
69 69
@@ -80,7 +80,7 @@ namespace OpenSim.Region.DataSnapshot
80 80
81 public Hashtable OnValidate(Hashtable keysvals) 81 public Hashtable OnValidate(Hashtable keysvals)
82 { 82 {
83 m_log.Info("[DATASNAPSHOT] Received validation request"); 83 m_log.Debug("[DATASNAPSHOT] Received validation request");
84 Hashtable reply = new Hashtable(); 84 Hashtable reply = new Hashtable();
85 int statuscode = 200; 85 int statuscode = 200;
86 86
diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
index dd48dd5..0c0a7aa 100644
--- a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
+++ b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
@@ -307,7 +307,7 @@ namespace OpenSim.Region.DataSnapshot
307 XmlNode regiondata = requestedSnap.CreateNode(XmlNodeType.Element, "regiondata", ""); 307 XmlNode regiondata = requestedSnap.CreateNode(XmlNodeType.Element, "regiondata", "");
308 try 308 try
309 { 309 {
310 if (regionName == null || regionName == "") 310 if (string.IsNullOrEmpty(regionName))
311 { 311 {
312 XmlNode timerblock = requestedSnap.CreateNode(XmlNodeType.Element, "expire", ""); 312 XmlNode timerblock = requestedSnap.CreateNode(XmlNodeType.Element, "expire", "");
313 timerblock.InnerText = m_period.ToString(); 313 timerblock.InnerText = m_period.ToString();
diff --git a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
index 0e7df07..3d74597 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/DataSnapshot/SnapshotStore.cs b/OpenSim/Region/DataSnapshot/SnapshotStore.cs
index aa3d2ff..480aaaf 100644
--- a/OpenSim/Region/DataSnapshot/SnapshotStore.cs
+++ b/OpenSim/Region/DataSnapshot/SnapshotStore.cs
@@ -120,7 +120,7 @@ namespace OpenSim.Region.DataSnapshot
120 provider.Stale = false; 120 provider.Stale = false;
121 m_scenes[provider.GetParentScene] = true; 121 m_scenes[provider.GetParentScene] = true;
122 122
123 m_log.Info("[DATASNAPSHOT]: Generated fragment response for provider type " + provider.Name); 123 m_log.Debug("[DATASNAPSHOT]: Generated fragment response for provider type " + provider.Name);
124 } 124 }
125 else 125 else
126 { 126 {
@@ -134,7 +134,7 @@ namespace OpenSim.Region.DataSnapshot
134 data = factory.ImportNode(node, true); 134 data = factory.ImportNode(node, true);
135 } 135 }
136 136
137 m_log.Info("[DATASNAPSHOT]: Retrieved fragment response for provider type " + provider.Name); 137 m_log.Debug("[DATASNAPSHOT]: Retrieved fragment response for provider type " + provider.Name);
138 } 138 }
139 139
140 return data; 140 return data;
@@ -154,7 +154,7 @@ namespace OpenSim.Region.DataSnapshot
154 154
155 if (!m_scenes[scene]) 155 if (!m_scenes[scene])
156 { 156 {
157 m_log.Info("[DATASNAPSHOT]: Attempting to retrieve snapshot from cache."); 157 m_log.Debug("[DATASNAPSHOT]: Attempting to retrieve snapshot from cache.");
158 //get snapshot from cache 158 //get snapshot from cache
159 String path = DataFileNameScene(scene); 159 String path = DataFileNameScene(scene);
160 160
@@ -168,11 +168,11 @@ namespace OpenSim.Region.DataSnapshot
168 regionElement = factory.ImportNode(node, true); 168 regionElement = factory.ImportNode(node, true);
169 } 169 }
170 170
171 m_log.Info("[DATASNAPSHOT]: Obtained snapshot from cache for " + scene.RegionInfo.RegionName); 171 m_log.Debug("[DATASNAPSHOT]: Obtained snapshot from cache for " + scene.RegionInfo.RegionName);
172 } 172 }
173 else 173 else
174 { 174 {
175 m_log.Info("[DATASNAPSHOT]: Attempting to generate snapshot."); 175 m_log.Debug("[DATASNAPSHOT]: Attempting to generate snapshot.");
176 //make snapshot 176 //make snapshot
177 regionElement = MakeRegionNode(scene, factory); 177 regionElement = MakeRegionNode(scene, factory);
178 178
@@ -211,7 +211,7 @@ namespace OpenSim.Region.DataSnapshot
211 211
212 m_scenes[scene] = false; 212 m_scenes[scene] = false;
213 213
214 m_log.Info("[DATASNAPSHOT]: Generated new snapshot for " + scene.RegionInfo.RegionName); 214 m_log.Debug("[DATASNAPSHOT]: Generated new snapshot for " + scene.RegionInfo.RegionName);
215 } 215 }
216 216
217 return regionElement; 217 return regionElement;
diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
index 21ed44f..b536a49 100644
--- a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
@@ -1,9 +1,30 @@
1//////////////////////////////////////////////////////////////// 1/*
2// 2 * Copyright (c) Contributors, http://opensimulator.org/
3// (c) 2009, 2010 Careminster Limited and Melanie Thielker 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4// 4 *
5// All rights reserved 5 * Redistribution and use in source and binary forms, with or without
6// 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
7using System; 28using System;
8using Nini.Config; 29using Nini.Config;
9using OpenSim.Framework; 30using OpenSim.Framework;
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 8028d87..eba881f 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -236,15 +236,17 @@ namespace OpenSim.Region.Framework.Interfaces
236 List<TaskInventoryItem> GetInventoryItems(InventoryType type); 236 List<TaskInventoryItem> GetInventoryItems(InventoryType type);
237 237
238 /// <summary> 238 /// <summary>
239 /// Get the scene object referenced by an inventory item. 239 /// Get the scene object(s) referenced by an inventory item.
240 /// </summary> 240 /// </summary>
241 /// 241 ///
242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have 242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have
243 /// been adjusted to reflect the part and item from which it originates. 243 /// been adjusted to reflect the part and item from which it originates.
244 /// 244 ///
245 /// <param name="item"></param> 245 /// <param name="item">Inventory item</param>
246 /// <returns>The scene object. Null if the scene object asset couldn't be found</returns> 246 /// <param name="objlist">The scene objects</param>
247 SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item); 247 /// <param name="veclist">Relative offsets for each object</param>
248 /// <returns>true = success, false = the scene object asset couldn't be found</returns>
249 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist);
248 250
249 /// <summary> 251 /// <summary>
250 /// Update an existing inventory item. 252 /// Update an existing inventory item.
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 1949a90..214b07a 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -47,13 +47,33 @@ namespace OpenSim.Region.Framework.Interfaces
47 /// The handle of the destination region. If it's the same as the region currently 47 /// The handle of the destination region. If it's the same as the region currently
48 /// occupied by the agent then the teleport will be within that region. 48 /// occupied by the agent then the teleport will be within that region.
49 /// </param> 49 /// </param>
50 /// <param name='agent'></param>
51 /// <param name='regionHandle'></param>
50 /// <param name='position'></param> 52 /// <param name='position'></param>
51 /// <param name='lookAt'></param> 53 /// <param name='lookAt'></param>
52 /// <param name='teleportFlags'></param> 54 /// <param name='teleportFlags'></param>
53 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); 55 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags);
54 56
57 /// <summary>
58 /// Teleports the agent for the given client to their home destination.
59 /// </summary>
60 /// <param name='id'></param>
61 /// <param name='client'></param>
55 bool TeleportHome(UUID id, IClientAPI client); 62 bool TeleportHome(UUID id, IClientAPI client);
56 63
64 /// <summary>
65 /// Teleport an agent directly to a given region without checking whether the region should be substituted.
66 /// </summary>
67 /// <remarks>
68 /// Please use Teleport() instead unless you know exactly what you're doing.
69 /// Do not use for same region teleports.
70 /// </remarks>
71 /// <param name='sp'></param>
72 /// <param name='reg'></param>
73 /// <param name='finalDestination'>/param>
74 /// <param name='position'></param>
75 /// <param name='lookAt'></param>
76 /// <param name='teleportFlags'></param>
57 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 77 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
58 Vector3 position, Vector3 lookAt, uint teleportFlags); 78 Vector3 position, Vector3 lookAt, uint teleportFlags);
59 79
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 292efa4..944c66b 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces
40 40
41 uint GetRegionFlags(); 41 uint GetRegionFlags();
42 bool IsManager(UUID avatarID); 42 bool IsManager(UUID avatarID);
43 43
44 /// <summary> 44 /// <summary>
45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.). 45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.).
46 /// </summary> 46 /// </summary>
@@ -54,5 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
54 54
55 void setEstateTerrainBaseTexture(int level, UUID texture); 55 void setEstateTerrainBaseTexture(int level, UUID texture);
56 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue); 56 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue);
57
58 /// <summary>
59 /// Returns whether the transfer ID is being used for a terrain transfer.
60 /// </summary>
61 bool IsTerrainXfer(ulong xferID);
57 } 62 }
58} 63}
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index 5512642..dfc269e 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -39,21 +39,22 @@ namespace OpenSim.Region.Framework.Interfaces
39 39
40 // These are required to decouple Scenes from EventQueueHelper 40 // These are required to decouple Scenes from EventQueueHelper
41 void DisableSimulator(ulong handle, UUID avatarID); 41 void DisableSimulator(ulong handle, UUID avatarID);
42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID); 42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY);
43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, 43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint,
44 string capsPath); 44 string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY);
45 void TeleportFinishEvent(ulong regionHandle, byte simAccess, 45 void TeleportFinishEvent(ulong regionHandle, byte simAccess,
46 IPEndPoint regionExternalEndPoint, 46 IPEndPoint regionExternalEndPoint,
47 uint locationID, uint flags, string capsURL, 47 uint locationID, uint flags, string capsURL,
48 UUID agentID); 48 UUID agentID, int regionSizeX, int regionSizeY);
49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, 49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
50 IPEndPoint newRegionExternalEndPoint, 50 IPEndPoint newRegionExternalEndPoint,
51 string capsURL, UUID avatarID, UUID sessionID); 51 string capsURL, UUID avatarID, UUID sessionID,
52 int regionSizeX, int regionSizeY);
52 void ChatterboxInvitation(UUID sessionID, string sessionName, 53 void ChatterboxInvitation(UUID sessionID, string sessionName,
53 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, 54 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
54 uint timeStamp, bool offline, int parentEstateID, Vector3 position, 55 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
55 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket); 56 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket);
56 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat, 57 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat,
57 bool isModerator, bool textMute); 58 bool isModerator, bool textMute);
58 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID); 59 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID);
59 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID); 60 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID);
diff --git a/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs b/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs
new file mode 100644
index 0000000..a730cfd
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs
@@ -0,0 +1,48 @@
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 OpenMetaverse;
30using OpenSim.Framework;
31using Caps=OpenSim.Framework.Capabilities.Caps;
32
33namespace OpenSim.Region.Framework.Interfaces
34{
35 public interface IExternalCapsModule
36 {
37 /// <summary>
38 /// This function extends the simple URL configuration in the caps handlers
39 /// to facilitate more interesting computation when an external handler is
40 /// sent to the viewer.
41 /// </summary>
42 /// <param name="agentID">New user UUID</param>
43 /// <param name="caps">Internal caps registry, where the external handler will be registered</param>
44 /// <param name="capName">Name of the specific cap we are registering</param>
45 /// <param name="urlSkel">The skeleton URL provided in the caps configuration</param>
46 bool RegisterExternalUserCapsHandler(UUID agentID, Caps caps, String capName, String urlSkel);
47 }
48}
diff --git a/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs b/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
index 6885327..9ae5e87 100644
--- a/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
@@ -97,5 +97,7 @@ namespace OpenSim.Region.Framework.Interfaces
97 void InviteGroupRequest(IClientAPI remoteClient, UUID GroupID, UUID InviteeID, UUID RoleID); 97 void InviteGroupRequest(IClientAPI remoteClient, UUID GroupID, UUID InviteeID, UUID RoleID);
98 void InviteGroup(IClientAPI remoteClient, UUID agentID, UUID GroupID, UUID InviteeID, UUID RoleID); 98 void InviteGroup(IClientAPI remoteClient, UUID agentID, UUID GroupID, UUID InviteeID, UUID RoleID);
99 void NotifyChange(UUID GroupID); 99 void NotifyChange(UUID GroupID);
100
101 List<DirGroupsReplyData> FindGroups(IClientAPI remoteClient, string query);
100 } 102 }
101} \ No newline at end of file 103} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
deleted file mode 100644
index 67a500f..0000000
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.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
28using OpenMetaverse;
29using OpenSim.Framework;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Framework.Interfaces
33{
34 public delegate bool ChildAgentUpdateReceived(AgentData data);
35
36 public interface IInterregionCommsOut
37 {
38 #region Agents
39
40 bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit, uint teleportFlags, out string reason);
41
42 /// <summary>
43 /// Full child agent update.
44 /// </summary>
45 /// <param name="regionHandle"></param>
46 /// <param name="data"></param>
47 /// <returns></returns>
48 bool SendChildAgentUpdate(ulong regionHandle, AgentData data);
49
50 /// <summary>
51 /// Short child agent update, mostly for position.
52 /// </summary>
53 /// <param name="regionHandle"></param>
54 /// <param name="data"></param>
55 /// <returns></returns>
56 bool SendChildAgentUpdate(ulong regionHandle, AgentPosition data);
57
58 bool SendRetrieveRootAgent(ulong regionHandle, UUID id, out IAgentData agent);
59
60 /// <summary>
61 /// Message from receiving region to departing region, telling it got contacted by the client.
62 /// When sent over REST, it invokes the opaque uri.
63 /// </summary>
64 /// <param name="regionHandle"></param>
65 /// <param name="id"></param>
66 /// <param name="uri"></param>
67 /// <returns></returns>
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69
70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
79 /// Close agent.
80 /// </summary>
81 /// <param name="regionHandle"></param>
82 /// <param name="id"></param>
83 /// <returns></returns>
84 bool SendCloseAgent(ulong regionHandle, UUID id);
85
86 #endregion Agents
87
88 #region Objects
89
90 /// <summary>
91 /// Create an object in the destination region. This message is used primarily for prim crossing.
92 /// </summary>
93 /// <param name="regionHandle"></param>
94 /// <param name="sog"></param>
95 /// <param name="isLocalCall"></param>
96 /// <returns></returns>
97 bool SendCreateObject(ulong regionHandle, SceneObjectGroup sog, bool isLocalCall);
98
99 /// <summary>
100 /// Create an object from the user's inventory in the destination region.
101 /// This message is used primarily by clients.
102 /// </summary>
103 /// <param name="regionHandle"></param>
104 /// <param name="userID"></param>
105 /// <param name="itemID"></param>
106 /// <returns></returns>
107 bool SendCreateObject(ulong regionHandle, UUID userID, UUID itemID);
108
109 #endregion Objects
110
111 }
112
113 // This may not be needed, but having it here for now.
114 public interface IInterregionCommsIn
115 {
116 event ChildAgentUpdateReceived OnChildAgentUpdate;
117 }
118
119}
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index b67312e..1a89721 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -51,10 +51,17 @@ namespace OpenSim.Region.Framework.Interfaces
51 UUID = 5 51 UUID = 5
52 } 52 }
53 53
54 public struct JsonStoreStats
55 {
56 public int StoreCount;
57 }
58
54 public delegate void TakeValueCallback(string s); 59 public delegate void TakeValueCallback(string s);
55 60
56 public interface IJsonStoreModule 61 public interface IJsonStoreModule
57 { 62 {
63 JsonStoreStats GetStoreStats();
64
58 bool AttachObjectStore(UUID objectID); 65 bool AttachObjectStore(UUID objectID);
59 bool CreateStore(string value, ref UUID result); 66 bool CreateStore(string value, ref UUID result);
60 bool DestroyStore(UUID storeID); 67 bool DestroyStore(UUID storeID);
diff --git a/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs b/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs
new file mode 100644
index 0000000..198256f
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs
@@ -0,0 +1,19 @@
1using System;
2using System.Collections.Generic;
3
4namespace OpenSim.Region.Framework.Interfaces
5{
6 public interface IServiceThrottleModule
7 {
8 /// <summary>
9 /// Enqueue a continuation meant to get a resource from elsewhere.
10 /// As usual with CPS, caller beware: if that continuation is a never-ending computation,
11 /// the whole thread will be blocked, and no requests are processed
12 /// </summary>
13 /// <param name="category">Category of the resource (e.g. name, region)</param>
14 /// <param name="itemid">The resource identifier</param>
15 /// <param name="continuation">The continuation to be executed</param>
16 void Enqueue(string category, string itemid, Action continuation);
17 }
18
19}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 68af492..8372ddd 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Interfaces
104 /// <param name="sound">Sound asset ID</param> 104 /// <param name="sound">Sound asset ID</param>
105 /// <param name="volume">Sound volume</param> 105 /// <param name="volume">Sound volume</param>
106 /// <param name="triggered">Triggered or not.</param> 106 /// <param name="triggered">Triggered or not.</param>
107 /// <param name="flags"></param>
108 /// <param name="radius">Sound radius</param> 107 /// <param name="radius">Sound radius</param>
109 /// <param name="useMaster">Play using sound master</param> 108 /// <param name="useMaster">Play using sound master</param>
110 /// <param name="isMaster">Play as sound master</param> 109 /// <param name="isMaster">Play as sound master</param>
@@ -123,5 +122,12 @@ namespace OpenSim.Region.Framework.Interfaces
123 /// <param name="max">AABB top north-east corner</param> 122 /// <param name="max">AABB top north-east corner</param>
124 void TriggerSoundLimited(UUID objectID, UUID sound, double volume, 123 void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
125 Vector3 min, Vector3 max); 124 Vector3 min, Vector3 max);
125
126 /// <summary>
127 /// Set whether sounds on the given prim should be queued.
128 /// </summary>
129 /// <param name='objectID'></param>
130 /// <param name='shouldQueue'></param>
131 void SetSoundQueueing(UUID objectID, bool shouldQueue);
126 } 132 }
127} \ No newline at end of file 133} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
index 167c248..a2a99d4 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
index 66edfed..b7400ea 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
@@ -28,8 +28,11 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Text;
31using log4net; 32using log4net;
32using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35
33using OpenSim.Framework; 36using OpenSim.Framework;
34 37
35using Animation = OpenSim.Framework.Animation; 38using Animation = OpenSim.Framework.Animation;
@@ -60,6 +63,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
60 ResetDefaultAnimation(); 63 ResetDefaultAnimation();
61 } 64 }
62 65
66 public AnimationSet(OSDArray pArray)
67 {
68 ResetDefaultAnimation();
69 FromOSDArray(pArray);
70 }
71
63 public bool HasAnimation(UUID animID) 72 public bool HasAnimation(UUID animID)
64 { 73 {
65 if (m_defaultAnimation.AnimID == animID) 74 if (m_defaultAnimation.AnimID == animID)
@@ -218,5 +227,110 @@ namespace OpenSim.Region.Framework.Scenes.Animation
218 foreach (OpenSim.Framework.Animation anim in theArray) 227 foreach (OpenSim.Framework.Animation anim in theArray)
219 m_animations.Add(anim); 228 m_animations.Add(anim);
220 } 229 }
230
231 // Create representation of this AnimationSet as an OSDArray.
232 // First two entries in the array are the default and implicitDefault animations
233 // followed by the other animations.
234 public OSDArray ToOSDArray()
235 {
236 OSDArray ret = new OSDArray();
237 ret.Add(DefaultAnimation.PackUpdateMessage());
238 ret.Add(ImplicitDefaultAnimation.PackUpdateMessage());
239
240 foreach (OpenSim.Framework.Animation anim in m_animations)
241 ret.Add(anim.PackUpdateMessage());
242
243 return ret;
244 }
245
246 public void FromOSDArray(OSDArray pArray)
247 {
248 this.Clear();
249
250 if (pArray.Count >= 1)
251 {
252 m_defaultAnimation = new OpenSim.Framework.Animation((OSDMap)pArray[0]);
253 }
254 if (pArray.Count >= 2)
255 {
256 m_implicitDefaultAnimation = new OpenSim.Framework.Animation((OSDMap)pArray[1]);
257 }
258 for (int ii = 2; ii < pArray.Count; ii++)
259 {
260 m_animations.Add(new OpenSim.Framework.Animation((OSDMap)pArray[ii]));
261 }
262 }
263
264 // Compare two AnimationSets and return 'true' if the default animations are the same
265 // and all of the animations in the list are equal.
266 public override bool Equals(object obj)
267 {
268 AnimationSet other = obj as AnimationSet;
269 if (other != null)
270 {
271 if (this.DefaultAnimation.Equals(other.DefaultAnimation)
272 && this.ImplicitDefaultAnimation.Equals(other.ImplicitDefaultAnimation))
273 {
274 // The defaults are the same. Is the list of animations the same?
275 OpenSim.Framework.Animation[] thisAnims = this.ToArray();
276 OpenSim.Framework.Animation[] otherAnims = other.ToArray();
277 if (thisAnims.Length == 0 && otherAnims.Length == 0)
278 return true; // the common case
279 if (thisAnims.Length == otherAnims.Length)
280 {
281 // Do this the hard way but since the list is usually short this won't take long.
282 foreach (OpenSim.Framework.Animation thisAnim in thisAnims)
283 {
284 bool found = false;
285 foreach (OpenSim.Framework.Animation otherAnim in otherAnims)
286 {
287 if (thisAnim.Equals(otherAnim))
288 {
289 found = true;
290 break;
291 }
292 }
293 if (!found)
294 {
295 // If anything is not in the other list, these are not equal
296 return false;
297 }
298 }
299 // Found everything in the other list. Since lists are equal length, they must be equal.
300 return true;
301 }
302 }
303 return false;
304 }
305 // Don't know what was passed, but the base system will figure it out for me.
306 return base.Equals(obj);
307 }
308
309 public override string ToString()
310 {
311 StringBuilder buff = new StringBuilder();
312 buff.Append("dflt=");
313 buff.Append(DefaultAnimation.ToString());
314 buff.Append(",iDflt=");
315 if (DefaultAnimation.Equals(ImplicitDefaultAnimation))
316 buff.Append("same");
317 else
318 buff.Append(ImplicitDefaultAnimation.ToString());
319 if (m_animations.Count > 0)
320 {
321 buff.Append(",anims=");
322 bool firstTime = true;
323 foreach (OpenSim.Framework.Animation anim in m_animations)
324 {
325 if (!firstTime)
326 buff.Append(",");
327 buff.Append("<");
328 buff.Append(anim.ToString());
329 buff.Append(">");
330 firstTime = false;
331 }
332 }
333 return buff.ToString();
334 }
221 } 335 }
222} 336}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs b/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
index c2b0468..b79dd8f 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
@@ -104,5 +104,31 @@ namespace OpenSim.Region.Framework.Scenes.Animation
104 104
105 return UUID.Zero; 105 return UUID.Zero;
106 } 106 }
107
108 /// <summary>
109 /// Get the name of the animation given a UUID. If there is no matching animation
110 /// return the UUID as a string.
111 /// </summary>
112 public static string GetDefaultAnimationName(UUID uuid)
113 {
114 string ret = "unknown";
115 if (AnimsUUID.ContainsValue(uuid))
116 {
117 foreach (KeyValuePair<string, UUID> kvp in AnimsUUID)
118 {
119 if (kvp.Value == uuid)
120 {
121 ret = kvp.Key;
122 break;
123 }
124 }
125 }
126 else
127 {
128 ret = uuid.ToString();
129 }
130
131 return ret;
132 }
107 } 133 }
108} \ No newline at end of file 134} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 65c279e..c1394aa 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -93,7 +93,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
93 GetAnimName(animID), animID, m_scenePresence.Name); 93 GetAnimName(animID), animID, m_scenePresence.Name);
94 94
95 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 95 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
96 {
96 SendAnimPack(); 97 SendAnimPack();
98 m_scenePresence.TriggerScenePresenceUpdated();
99 }
97 } 100 }
98 101
99 // Called from scripts 102 // Called from scripts
@@ -132,7 +135,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
132 GetAnimName(animID), animID, m_scenePresence.Name); 135 GetAnimName(animID), animID, m_scenePresence.Name);
133 136
134 if (m_animations.Remove(animID, allowNoDefault)) 137 if (m_animations.Remove(animID, allowNoDefault))
138 {
135 SendAnimPack(); 139 SendAnimPack();
140 m_scenePresence.TriggerScenePresenceUpdated();
141 }
136 } 142 }
137 143
138 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack) 144 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack)
@@ -180,8 +186,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
180 /// The movement animation is reserved for "main" animations 186 /// The movement animation is reserved for "main" animations
181 /// that are mutually exclusive, e.g. flying and sitting. 187 /// that are mutually exclusive, e.g. flying and sitting.
182 /// </summary> 188 /// </summary>
183 public void TrySetMovementAnimation(string anim) 189 /// <returns>'true' if the animation was updated</returns>
190 public bool TrySetMovementAnimation(string anim)
184 { 191 {
192 bool ret = false;
185 if (!m_scenePresence.IsChildAgent) 193 if (!m_scenePresence.IsChildAgent)
186 { 194 {
187// m_log.DebugFormat( 195// m_log.DebugFormat(
@@ -198,6 +206,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
198 // 16384 is CHANGED_ANIMATION 206 // 16384 is CHANGED_ANIMATION
199 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); 207 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION});
200 SendAnimPack(); 208 SendAnimPack();
209 ret = true;
201 } 210 }
202 } 211 }
203 else 212 else
@@ -206,6 +215,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
206 "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", 215 "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}",
207 anim, m_scenePresence.Name); 216 anim, m_scenePresence.Name);
208 } 217 }
218 return ret;
209 } 219 }
210 220
211 /// <summary> 221 /// <summary>
@@ -410,11 +420,18 @@ namespace OpenSim.Region.Framework.Scenes.Animation
410 Falling = false; 420 Falling = false;
411 // Walking / crouchwalking / running 421 // Walking / crouchwalking / running
412 if (move.Z < 0f) 422 if (move.Z < 0f)
423 {
413 return "CROUCHWALK"; 424 return "CROUCHWALK";
414 else if (m_scenePresence.SetAlwaysRun) 425 }
415 return "RUN"; 426 // We need to prevent these animations if the user tries to make their avatar walk or run whilst
416 else 427 // specifying AGENT_CONTROL_STOP (pressing down space on viewers).
417 return "WALK"; 428 else if (!m_scenePresence.AgentControlStopActive)
429 {
430 if (m_scenePresence.SetAlwaysRun)
431 return "RUN";
432 else
433 return "WALK";
434 }
418 } 435 }
419 else if (!m_jumping) 436 else if (!m_jumping)
420 { 437 {
@@ -439,8 +456,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
439 /// <summary> 456 /// <summary>
440 /// Update the movement animation of this avatar according to its current state 457 /// Update the movement animation of this avatar according to its current state
441 /// </summary> 458 /// </summary>
442 public void UpdateMovementAnimations() 459 /// <returns>'true' if the animation was changed</returns>
460 public bool UpdateMovementAnimations()
443 { 461 {
462// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name);
463
464 bool ret = false;
444 lock (m_animations) 465 lock (m_animations)
445 { 466 {
446 string newMovementAnimation = DetermineMovementAnimation(); 467 string newMovementAnimation = DetermineMovementAnimation();
@@ -454,9 +475,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
454 475
455 // Only set it if it's actually changed, give a script 476 // Only set it if it's actually changed, give a script
456 // a chance to stop a default animation 477 // a chance to stop a default animation
457 TrySetMovementAnimation(CurrentMovementAnimation); 478 ret = TrySetMovementAnimation(CurrentMovementAnimation);
458 } 479 }
459 } 480 }
481 return ret;
460 } 482 }
461 483
462 public UUID[] GetAnimationArray() 484 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index f555b49..11a0146 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,14 +104,8 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
109 foreach (SceneObjectGroup g in objectGroups) 107 foreach (SceneObjectGroup g in objectGroups)
110 { killIDs.Add(g.LocalId); 108 g.DeleteGroupFromScene(false);
111 g.DeleteGroupFromScene(true);
112 }
113
114 m_scene.SendKillObject(killIDs);
115 } 109 }
116 } 110 }
117 111
@@ -160,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
160 if (x.permissionToDelete) 154 if (x.permissionToDelete)
161 { 155 {
162 foreach (SceneObjectGroup g in x.objectGroups) 156 foreach (SceneObjectGroup g in x.objectGroups)
163 m_scene.DeleteSceneObject(g, false); 157 m_scene.DeleteSceneObject(g, true);
164 } 158 }
165 } 159 }
166 catch (Exception e) 160 catch (Exception e)
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 4733547..7f06e82 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -148,7 +148,7 @@ namespace OpenSim.Region.Framework.Scenes
148 /// Triggered when a new presence is added to the scene 148 /// Triggered when a new presence is added to the scene
149 /// </summary> 149 /// </summary>
150 /// <remarks> 150 /// <remarks>
151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both 151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
153 /// </remarks> 153 /// </remarks>
154 public event OnNewPresenceDelegate OnNewPresence; 154 public event OnNewPresenceDelegate OnNewPresence;
@@ -159,7 +159,7 @@ namespace OpenSim.Region.Framework.Scenes
159 /// Triggered when a presence is removed from the scene 159 /// Triggered when a presence is removed from the scene
160 /// </summary> 160 /// </summary>
161 /// <remarks> 161 /// <remarks>
162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both 162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
164 /// 164 ///
165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please 165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please
@@ -743,7 +743,7 @@ namespace OpenSim.Region.Framework.Scenes
743 public event OnIncomingSceneObjectDelegate OnIncomingSceneObject; 743 public event OnIncomingSceneObjectDelegate OnIncomingSceneObject;
744 public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so); 744 public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so);
745 745
746 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); 746 public delegate void NewInventoryItemUploadComplete(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel);
747 747
748 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; 748 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete;
749 749
@@ -974,6 +974,8 @@ namespace OpenSim.Region.Framework.Scenes
974 public delegate void RegionStarted(Scene scene); 974 public delegate void RegionStarted(Scene scene);
975 public event RegionStarted OnRegionStarted; 975 public event RegionStarted OnRegionStarted;
976 976
977 public delegate void RegionHeartbeatStart(Scene scene);
978 public event RegionHeartbeatStart OnRegionHeartbeatStart;
977 public delegate void RegionHeartbeatEnd(Scene scene); 979 public delegate void RegionHeartbeatEnd(Scene scene);
978 public event RegionHeartbeatEnd OnRegionHeartbeatEnd; 980 public event RegionHeartbeatEnd OnRegionHeartbeatEnd;
979 981
@@ -1024,6 +1026,16 @@ namespace OpenSim.Region.Framework.Scenes
1024 /// </remarks> 1026 /// </remarks>
1025 public event TeleportFail OnTeleportFail; 1027 public event TeleportFail OnTeleportFail;
1026 1028
1029// public delegate void GatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids);
1030//
1031// /// <summary>
1032// /// Triggered when UUIDs referenced by a scene object are being gathered for archiving, hg transfer, etc.
1033// /// </summary>
1034// /// <remarks>
1035// /// The listener should add references to the IDictionary<UUID, AssetType> as appropriate.
1036// /// </remarks>
1037// public event GatherUuids OnGatherUuids;
1038
1027 public class MoneyTransferArgs : EventArgs 1039 public class MoneyTransferArgs : EventArgs
1028 { 1040 {
1029 public UUID sender; 1041 public UUID sender;
@@ -1095,7 +1107,7 @@ namespace OpenSim.Region.Framework.Scenes
1095 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/> 1107 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
1096 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/> 1108 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
1097 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/> 1109 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
1098 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> 1110 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/>
1099 /// </remarks> 1111 /// </remarks>
1100 public event MoneyTransferEvent OnMoneyTransfer; 1112 public event MoneyTransferEvent OnMoneyTransfer;
1101 1113
@@ -2160,7 +2172,7 @@ namespace OpenSim.Region.Framework.Scenes
2160 } 2172 }
2161 } 2173 }
2162 2174
2163 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, UUID AssetID, String AssetName, int userlevel) 2175 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, AssetType type, UUID AssetID, String AssetName, int userlevel)
2164 { 2176 {
2165 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; 2177 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete;
2166 if (handlerNewInventoryItemUpdateComplete != null) 2178 if (handlerNewInventoryItemUpdateComplete != null)
@@ -2169,7 +2181,7 @@ namespace OpenSim.Region.Framework.Scenes
2169 { 2181 {
2170 try 2182 try
2171 { 2183 {
2172 d(agentID, AssetID, AssetName, userlevel); 2184 d(agentID, type, AssetID, AssetName, userlevel);
2173 } 2185 }
2174 catch (Exception e) 2186 catch (Exception e)
2175 { 2187 {
@@ -3096,6 +3108,27 @@ namespace OpenSim.Region.Framework.Scenes
3096 } 3108 }
3097 } 3109 }
3098 3110
3111 public void TriggerRegionHeartbeatStart(Scene scene)
3112 {
3113 RegionHeartbeatStart handler = OnRegionHeartbeatStart;
3114
3115 if (handler != null)
3116 {
3117 foreach (RegionHeartbeatStart d in handler.GetInvocationList())
3118 {
3119 try
3120 {
3121 d(scene);
3122 }
3123 catch (Exception e)
3124 {
3125 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionHeartbeatStart failed - continuing {0} - {1}",
3126 e.Message, e.StackTrace);
3127 }
3128 }
3129 }
3130 }
3131
3099 public void TriggerRegionHeartbeatEnd(Scene scene) 3132 public void TriggerRegionHeartbeatEnd(Scene scene)
3100 { 3133 {
3101 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd; 3134 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd;
@@ -3251,5 +3284,26 @@ namespace OpenSim.Region.Framework.Scenes
3251 handler(scenePresence); 3284 handler(scenePresence);
3252 } 3285 }
3253 } 3286 }
3287
3288// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids)
3289// {
3290// GatherUuids handler = OnGatherUuids;
3291//
3292// if (handler != null)
3293// {
3294// foreach (GatherUuids d in handler.GetInvocationList())
3295// {
3296// try
3297// {
3298// d(sop, assetUuids);
3299// }
3300// catch (Exception e)
3301// {
3302// m_log.ErrorFormat("[EVENT MANAGER]: Delegate for TriggerUuidGather failed - continuing {0} - {1}",
3303// e.Message, e.StackTrace);
3304// }
3305// }
3306// }
3307// }
3254 } 3308 }
3255} 3309}
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index 276b61f..4d153da 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -1,6 +1,29 @@
1// Proprietary code of Avination Virtual Limited 1/*
2// (c) 2012 Melanie Thielker 2 * Copyright (c) Contributors, http://opensimulator.org/
3// 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 */
4 27
5using System; 28using System;
6using System.Timers; 29using System.Timers;
@@ -32,7 +55,6 @@ namespace OpenSim.Region.Framework.Scenes
32 private object m_lockObject = new object(); 55 private object m_lockObject = new object();
33 private object m_timerLock = new object(); 56 private object m_timerLock = new object();
34 private const double m_tickDuration = 50.0; 57 private const double m_tickDuration = 50.0;
35 private Scene m_scene;
36 58
37 public double TickDuration 59 public double TickDuration
38 { 60 {
@@ -46,8 +68,6 @@ namespace OpenSim.Region.Framework.Scenes
46 m_timer.AutoReset = true; 68 m_timer.AutoReset = true;
47 m_timer.Elapsed += OnTimer; 69 m_timer.Elapsed += OnTimer;
48 70
49 m_scene = scene;
50
51 m_timer.Start(); 71 m_timer.Start();
52 } 72 }
53 73
@@ -71,13 +91,13 @@ namespace OpenSim.Region.Framework.Scenes
71 { 91 {
72 m.OnTimer(TickDuration); 92 m.OnTimer(TickDuration);
73 } 93 }
74 catch (Exception inner) 94 catch (Exception)
75 { 95 {
76 // Don't stop processing 96 // Don't stop processing
77 } 97 }
78 } 98 }
79 } 99 }
80 catch (Exception e) 100 catch (Exception)
81 { 101 {
82 // Keep running no matter what 102 // Keep running no matter what
83 } 103 }
@@ -134,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
134 [Serializable] 154 [Serializable]
135 public class KeyframeMotion 155 public class KeyframeMotion
136 { 156 {
137 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 157// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
138 158
139 public enum PlayMode : int 159 public enum PlayMode : int
140 { 160 {
@@ -478,6 +498,7 @@ namespace OpenSim.Region.Framework.Scenes
478 k.Position = pos; 498 k.Position = pos;
479// k.Velocity = Vector3.Zero; 499// k.Velocity = Vector3.Zero;
480 } 500 }
501 k.AngularVelocity = (Vector3)k.Position;
481 502
482 k.StartRotation = rot; 503 k.StartRotation = rot;
483 if (k.Rotation.HasValue) 504 if (k.Rotation.HasValue)
@@ -618,7 +639,7 @@ namespace OpenSim.Region.Framework.Scenes
618 m_group.RootPart.Velocity = Vector3.Zero; 639 m_group.RootPart.Velocity = Vector3.Zero;
619 m_group.RootPart.AngularVelocity = Vector3.Zero; 640 m_group.RootPart.AngularVelocity = Vector3.Zero;
620 641
621 m_nextPosition = (Vector3)m_currentFrame.Position; 642 m_nextPosition = NormalizeVector(m_currentFrame.AngularVelocity);
622 m_group.AbsolutePosition = m_nextPosition; 643 m_group.AbsolutePosition = m_nextPosition;
623 644
624 // we are sending imediate updates, no doing force a extra terseUpdate 645 // we are sending imediate updates, no doing force a extra terseUpdate
@@ -706,7 +727,26 @@ namespace OpenSim.Region.Framework.Scenes
706 m_group.SendGroupRootTerseUpdate(); 727 m_group.SendGroupRootTerseUpdate();
707 } 728 }
708 } 729 }
730 private Vector3 NormalizeVector(Vector3? pPosition)
731 {
732 if (pPosition == null)
733 return Vector3.Zero;
734
735 Vector3 tmp = (Vector3) pPosition;
709 736
737 while (tmp.X > Constants.RegionSize)
738 tmp.X -= Constants.RegionSize;
739 while (tmp.X < 0)
740 tmp.X += Constants.RegionSize;
741 while (tmp.Y > Constants.RegionSize)
742 tmp.Y -= Constants.RegionSize;
743 while (tmp.Y < 0)
744 tmp.Y += Constants.RegionSize;
745
746 return tmp;
747
748
749 }
710 public Byte[] Serialize() 750 public Byte[] Serialize()
711 { 751 {
712 StopTimer(); 752 StopTimer();
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
index c11174d..f208afb 100644
--- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
+++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
@@ -46,47 +46,33 @@ using OpenSim.Region.Framework.Scenes;
46 46
47namespace OpenSim.Region.Framework.Scenes 47namespace OpenSim.Region.Framework.Scenes
48{ 48{
49 public class RegionStatsHandler : IStreamedRequestHandler 49 public class RegionStatsHandler : BaseStreamHandler
50 { 50 {
51 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 private string osRXStatsURI = String.Empty;
54 private string osXStatsURI = String.Empty; 53 private string osXStatsURI = String.Empty;
55 //private string osSecret = String.Empty; 54 //private string osSecret = String.Empty;
56 private OpenSim.Framework.RegionInfo regionInfo; 55 private OpenSim.Framework.RegionInfo regionInfo;
57 public string localZone = TimeZone.CurrentTimeZone.StandardName; 56 public string localZone = TimeZone.CurrentTimeZone.StandardName;
58 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); 57 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
59 58
60 public string Name { get { return "RegionStats"; } } 59 public RegionStatsHandler(RegionInfo region_info)
61 public string Description { get { return "Region Statistics"; } } 60 : base("GET", "/" + Util.SHA1Hash(region_info.regionSecret), "RegionStats", "Region Statistics")
62
63 public RegionStatsHandler(RegionInfo region_info)
64 { 61 {
65 regionInfo = region_info; 62 regionInfo = region_info;
66 osRXStatsURI = Util.SHA1Hash(regionInfo.regionSecret);
67 osXStatsURI = Util.SHA1Hash(regionInfo.osSecret); 63 osXStatsURI = Util.SHA1Hash(regionInfo.osSecret);
68 } 64 }
69 65
70 public byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 protected override byte[] ProcessRequest(
67 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
71 { 68 {
72 return Util.UTF8.GetBytes(Report()); 69 return Util.UTF8.GetBytes(Report());
73 } 70 }
74 71
75 public string ContentType 72 public override string ContentType
76 { 73 {
77 get { return "text/plain"; } 74 get { return "text/plain"; }
78 } 75 }
79
80 public string HttpMethod
81 {
82 get { return "GET"; }
83 }
84
85 public string Path
86 {
87 // This is for the region and is the regionSecret hashed
88 get { return "/" + osRXStatsURI; }
89 }
90 76
91 private string Report() 77 private string Report()
92 { 78 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index d2e41f8..cba75f1 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -31,6 +31,7 @@ using System.Collections;
31using System.Reflection; 31using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Timers; 33using System.Timers;
34using System.Xml;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
36using log4net; 37using log4net;
@@ -139,7 +140,7 @@ namespace OpenSim.Region.Framework.Scenes
139 { 140 {
140 userlevel = 1; 141 userlevel = 1;
141 } 142 }
142 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); 143 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
143 144
144 return true; 145 return true;
145 } 146 }
@@ -178,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
178 { 179 {
179 userlevel = 1; 180 userlevel = 1;
180 } 181 }
181 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); 182 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
182 183
183 if (originalFolder != UUID.Zero) 184 if (originalFolder != UUID.Zero)
184 { 185 {
@@ -411,19 +412,21 @@ namespace OpenSim.Region.Framework.Scenes
411// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags, 412// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags,
412// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions); 413// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions);
413 414
415 bool sendUpdate = false;
416
414 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid 417 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid
415 { 418 {
416 // Create a set of base permissions that will not include export if the user 419 // Create a set of base permissions that will not include export if the user
417 // is not allowed to change the export flag. 420 // is not allowed to change the export flag.
418 bool denyExportChange = false; 421 bool denyExportChange = false;
419 422
420 m_log.InfoFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions); 423// m_log.DebugFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions);
421 424
422 // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export 425 // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export
423 if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner) 426 if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner)
424 denyExportChange = true; 427 denyExportChange = true;
425 428
426 m_log.InfoFormat("[XXX]: Deny Export Update {0}", denyExportChange); 429// m_log.DebugFormat("[XXX]: Deny Export Update {0}", denyExportChange);
427 430
428 // If it is already set, force it set and also force full perm 431 // If it is already set, force it set and also force full perm
429 // else prevent setting it. It can and should never be set unless 432 // else prevent setting it. It can and should never be set unless
@@ -447,7 +450,7 @@ namespace OpenSim.Region.Framework.Scenes
447 // If the new state is exportable, force full perm 450 // If the new state is exportable, force full perm
448 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0) 451 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0)
449 { 452 {
450 m_log.InfoFormat("[XXX]: Force full perm"); 453// m_log.DebugFormat("[XXX]: Force full perm");
451 itemUpd.NextPermissions = (uint)(PermissionMask.All); 454 itemUpd.NextPermissions = (uint)(PermissionMask.All);
452 } 455 }
453 } 456 }
@@ -484,8 +487,13 @@ namespace OpenSim.Region.Framework.Scenes
484 item.SalePrice = itemUpd.SalePrice; 487 item.SalePrice = itemUpd.SalePrice;
485 item.SaleType = itemUpd.SaleType; 488 item.SaleType = itemUpd.SaleType;
486 489
490 if (item.InvType == (int)InventoryType.Wearable && (item.Flags & 0xf) == 0 && (itemUpd.Flags & 0xf) != 0)
491 {
492 item.Flags = (uint)(item.Flags & 0xfffffff0) | (itemUpd.Flags & 0xf);
493 sendUpdate = true;
494 }
495
487 InventoryService.UpdateItem(item); 496 InventoryService.UpdateItem(item);
488 remoteClient.SendBulkUpdateInventory(item);
489 } 497 }
490 498
491 if (UUID.Zero != transactionID) 499 if (UUID.Zero != transactionID)
@@ -495,6 +503,17 @@ namespace OpenSim.Region.Framework.Scenes
495 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); 503 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
496 } 504 }
497 } 505 }
506 else
507 {
508 // This MAY be problematic, if it is, another solution
509 // needs to be found. If inventory item flags are updated
510 // the viewer's notion of the item needs to be refreshed.
511 //
512 // In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start
513 // failing frequently. Possibly this is a race with a separate transaction that uploads the asset.
514 if (sendUpdate)
515 remoteClient.SendBulkUpdateInventory(item);
516 }
498 } 517 }
499 else 518 else
500 { 519 {
@@ -548,6 +567,9 @@ namespace OpenSim.Region.Framework.Scenes
548 { 567 {
549 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem"); 568 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem");
550 569
570 if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient))
571 return null;
572
551 InventoryItemBase item = new InventoryItemBase(itemId, senderId); 573 InventoryItemBase item = new InventoryItemBase(itemId, senderId);
552 item = InventoryService.GetItem(item); 574 item = InventoryService.GetItem(item);
553 575
@@ -642,17 +664,13 @@ namespace OpenSim.Region.Framework.Scenes
642 // a mask 664 // a mask
643 if (item.InvType == (int)InventoryType.Object) 665 if (item.InvType == (int)InventoryType.Object)
644 { 666 {
645 // Create a safe mask for the current perms
646 uint foldedPerms = (item.CurrentPermissions & 7) << 13;
647 foldedPerms |= permsMask;
648
649 bool isRootMod = (item.CurrentPermissions & 667 bool isRootMod = (item.CurrentPermissions &
650 (uint)PermissionMask.Modify) != 0 ? 668 (uint)PermissionMask.Modify) != 0 ?
651 true : false; 669 true : false;
652 670
653 // Mask the owner perms to the folded perms 671 // Mask the owner perms to the folded perms
654 ownerPerms &= foldedPerms; 672 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref ownerPerms);
655 basePerms &= foldedPerms; 673 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref basePerms);
656 674
657 // If the root was mod, let the mask reflect that 675 // If the root was mod, let the mask reflect that
658 // We also need to adjust the base here, because 676 // We also need to adjust the base here, because
@@ -1213,9 +1231,16 @@ namespace OpenSim.Region.Framework.Scenes
1213 { 1231 {
1214 agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); 1232 agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
1215 if (taskItem.InvType == (int)InventoryType.Object) 1233 if (taskItem.InvType == (int)InventoryType.Object)
1216 agentItem.CurrentPermissions = agentItem.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); 1234 {
1235 uint perms = taskItem.CurrentPermissions;
1236 PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms);
1237 agentItem.BasePermissions = perms | (uint)PermissionMask.Move;
1238 agentItem.CurrentPermissions = agentItem.BasePermissions;
1239 }
1217 else 1240 else
1241 {
1218 agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; 1242 agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions;
1243 }
1219 1244
1220 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; 1245 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
1221 agentItem.NextPermissions = taskItem.NextPermissions; 1246 agentItem.NextPermissions = taskItem.NextPermissions;
@@ -2124,7 +2149,10 @@ namespace OpenSim.Region.Framework.Scenes
2124 { 2149 {
2125 // If we don't have permission, stop right here 2150 // If we don't have permission, stop right here
2126 if (!permissionToTakeCopy) 2151 if (!permissionToTakeCopy)
2152 {
2153 remoteClient.SendAlertMessage("You don't have permission to take the object");
2127 return; 2154 return;
2155 }
2128 2156
2129 permissionToTake = true; 2157 permissionToTake = true;
2130 // Don't delete 2158 // Don't delete
@@ -2277,6 +2305,85 @@ namespace OpenSim.Region.Framework.Scenes
2277 } 2305 }
2278 2306
2279 /// <summary> 2307 /// <summary>
2308 /// Returns the list of Scene Objects in an asset.
2309 /// </summary>
2310 /// <remarks>
2311 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2312 /// </remarks>
2313 /// <param name="assetData">Asset data</param>
2314 /// <param name="attachment">Whether the item is an attachment</param>
2315 /// <param name="objlist">The objects included in the asset</param>
2316 /// <param name="veclist">Relative positions of the objects</param>
2317 /// <param name="bbox">Bounding box of all the objects</param>
2318 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2319 /// to the centre of the root prim (relevant only when returning a single object)</param>
2320 /// <returns>true = returning a single object; false = multiple objects</returns>
2321 public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2322 out Vector3 bbox, out float offsetHeight)
2323 {
2324 objlist = new List<SceneObjectGroup>();
2325 veclist = new List<Vector3>();
2326
2327 XmlDocument doc = new XmlDocument();
2328 string xmlData = Utils.BytesToString(assetData);
2329 doc.LoadXml(xmlData);
2330 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2331
2332 if (e == null || attachment) // Single
2333 {
2334 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
2335
2336 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2337 g.RootPart.AttachOffset = g.AbsolutePosition;
2338 g.RootPart.AttachRotation = g.GroupRotation;
2339 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2340 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2341 g.RootPart.Shape.State = 0;
2342
2343 objlist.Add(g);
2344 veclist.Add(new Vector3(0, 0, 0));
2345 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2346 return true;
2347 }
2348 else
2349 {
2350 XmlElement coll = (XmlElement)e;
2351 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2352 float by = Convert.ToSingle(coll.GetAttribute("y"));
2353 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2354 bbox = new Vector3(bx, by, bz);
2355 offsetHeight = 0;
2356
2357 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2358 foreach (XmlNode n in groups)
2359 {
2360 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2361
2362 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2363 g.RootPart.AttachOffset = g.AbsolutePosition;
2364 g.RootPart.AttachRotation = g.GroupRotation;
2365 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2366 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2367 g.RootPart.Shape.State = 0;
2368
2369 objlist.Add(g);
2370
2371 XmlElement el = (XmlElement)n;
2372 string rawX = el.GetAttribute("offsetx");
2373 string rawY = el.GetAttribute("offsety");
2374 string rawZ = el.GetAttribute("offsetz");
2375
2376 float x = Convert.ToSingle(rawX);
2377 float y = Convert.ToSingle(rawY);
2378 float z = Convert.ToSingle(rawZ);
2379 veclist.Add(new Vector3(x, y, z));
2380 }
2381 }
2382
2383 return false;
2384 }
2385
2386 /// <summary>
2280 /// Event Handler Rez an object into a scene 2387 /// Event Handler Rez an object into a scene
2281 /// Calls the non-void event handler 2388 /// Calls the non-void event handler
2282 /// </summary> 2389 /// </summary>
@@ -2351,19 +2458,25 @@ namespace OpenSim.Region.Framework.Scenes
2351 /// will be used if it exists.</param> 2458 /// will be used if it exists.</param>
2352 /// <param name="vel">The velocity of the rezzed object.</param> 2459 /// <param name="vel">The velocity of the rezzed object.</param>
2353 /// <param name="param"></param> 2460 /// <param name="param"></param>
2354 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2461 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2355 public virtual SceneObjectGroup RezObject( 2462 public virtual List<SceneObjectGroup> RezObject(
2356 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2463 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
2357 { 2464 {
2358 if (null == item) 2465 if (null == item)
2359 return null; 2466 return null;
2467
2468 List<SceneObjectGroup> objlist;
2469 List<Vector3> veclist;
2360 2470
2361 SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); 2471 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
2362 2472 if (!success)
2363 if (null == group)
2364 return null; 2473 return null;
2365 2474
2366 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) 2475 int totalPrims = 0;
2476 foreach (SceneObjectGroup group in objlist)
2477 totalPrims += group.PrimCount;
2478
2479 if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
2367 return null; 2480 return null;
2368 2481
2369 if (!Permissions.BypassPermissions()) 2482 if (!Permissions.BypassPermissions())
@@ -2372,16 +2485,28 @@ namespace OpenSim.Region.Framework.Scenes
2372 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2485 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2373 } 2486 }
2374 2487
2375 group.FromPartID = sourcePart.UUID; 2488 for (int i = 0; i < objlist.Count; i++)
2376 AddNewSceneObject(group, true, pos, rot, vel); 2489 {
2377 2490 SceneObjectGroup group = objlist[i];
2378 // We can only call this after adding the scene object, since the scene object references the scene 2491 Vector3 curpos = pos + veclist[i];
2379 // to find out if scripts should be activated at all. 2492
2380 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); 2493 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2381 2494 {
2382 group.ScheduleGroupForFullUpdate(); 2495 group.RootPart.AttachedPos = group.AbsolutePosition;
2383 2496 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2384 return group; 2497 }
2498
2499 group.FromPartID = sourcePart.UUID;
2500 AddNewSceneObject(group, true, curpos, rot, vel);
2501
2502 // We can only call this after adding the scene object, since the scene object references the scene
2503 // to find out if scripts should be activated at all.
2504 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2505
2506 group.ScheduleGroupForFullUpdate();
2507 }
2508
2509 return objlist;
2385 } 2510 }
2386 2511
2387 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, 2512 public virtual bool returnObjects(SceneObjectGroup[] returnobjects,
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index ce6415a..46b2d2e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -252,8 +252,6 @@ namespace OpenSim.Region.Framework.Scenes
252 if (part.ParentGroup.RootPart.LocalId != part.LocalId) 252 if (part.ParentGroup.RootPart.LocalId != part.LocalId)
253 return; 253 return;
254 254
255 bool isAttachment = false;
256
257 // This is wrong, wrong, wrong. Selection should not be 255 // This is wrong, wrong, wrong. Selection should not be
258 // handled by group, but by prim. Legacy cruft. 256 // handled by group, but by prim. Legacy cruft.
259 // TODO: Make selection flagging per prim! 257 // TODO: Make selection flagging per prim!
@@ -262,17 +260,14 @@ namespace OpenSim.Region.Framework.Scenes
262 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) 260 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
263 part.ParentGroup.IsSelected = false; 261 part.ParentGroup.IsSelected = false;
264 262
265 if (part.ParentGroup.IsAttachment) 263 part.ParentGroup.ScheduleGroupForFullUpdate();
266 isAttachment = true;
267 else
268 part.ParentGroup.ScheduleGroupForFullUpdate();
269 264
270 // If it's not an attachment, and we are allowed to move it, 265 // If it's not an attachment, and we are allowed to move it,
271 // then we might have done so. If we moved across a parcel 266 // then we might have done so. If we moved across a parcel
272 // boundary, we will need to recount prims on the parcels. 267 // boundary, we will need to recount prims on the parcels.
273 // For attachments, that makes no sense. 268 // For attachments, that makes no sense.
274 // 269 //
275 if (!isAttachment) 270 if (!part.ParentGroup.IsAttachment)
276 { 271 {
277 if (Permissions.CanEditObject( 272 if (Permissions.CanEditObject(
278 part.UUID, remoteClient.AgentId) 273 part.UUID, remoteClient.AgentId)
@@ -416,6 +411,7 @@ namespace OpenSim.Region.Framework.Scenes
416 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) 411 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args)
417 { 412 {
418 // TODO: don't create new blocks if recycling an old packet 413 // TODO: don't create new blocks if recycling an old packet
414 bool discardableEffects = true;
419 ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; 415 ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count];
420 for (int i = 0; i < args.Count; i++) 416 for (int i = 0; i < args.Count; i++)
421 { 417 {
@@ -427,17 +423,34 @@ namespace OpenSim.Region.Framework.Scenes
427 effect.Type = args[i].Type; 423 effect.Type = args[i].Type;
428 effect.TypeData = args[i].TypeData; 424 effect.TypeData = args[i].TypeData;
429 effectBlockArray[i] = effect; 425 effectBlockArray[i] = effect;
426
427 if ((EffectType)effect.Type != EffectType.LookAt && (EffectType)effect.Type != EffectType.Beam)
428 discardableEffects = false;
429
430 //m_log.DebugFormat("[YYY]: VE {0} {1} {2}", effect.AgentID, effect.Duration, (EffectType)effect.Type);
430 } 431 }
431 432
432 ForEachClient( 433 ForEachScenePresence(sp =>
433 delegate(IClientAPI client)
434 { 434 {
435 if (client.AgentId != remoteClient.AgentId) 435 if (sp.ControllingClient.AgentId != remoteClient.AgentId)
436 client.SendViewerEffect(effectBlockArray); 436 {
437 } 437 if (!discardableEffects ||
438 ); 438 (discardableEffects && ShouldSendDiscardableEffect(remoteClient, sp)))
439 {
440 //m_log.DebugFormat("[YYY]: Sending to {0}", sp.UUID);
441 sp.ControllingClient.SendViewerEffect(effectBlockArray);
442 }
443 //else
444 // m_log.DebugFormat("[YYY]: Not sending to {0}", sp.UUID);
445 }
446 });
439 } 447 }
440 448
449 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other)
450 {
451 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10;
452 }
453
441 private class DescendentsRequestData 454 private class DescendentsRequestData
442 { 455 {
443 public IClientAPI RemoteClient; 456 public IClientAPI RemoteClient;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index b189599..55766cf 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -151,7 +151,7 @@ namespace OpenSim.Region.Framework.Scenes
151 public SynchronizeSceneHandler SynchronizeScene; 151 public SynchronizeSceneHandler SynchronizeScene;
152 152
153 /// <summary> 153 /// <summary>
154 /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. 154 /// Used to prevent simultaneous calls to code that adds and removes agents.
155 /// </summary> 155 /// </summary>
156 private object m_removeClientLock = new object(); 156 private object m_removeClientLock = new object();
157 157
@@ -230,6 +230,8 @@ namespace OpenSim.Region.Framework.Scenes
230 public bool m_seeIntoBannedRegion = false; 230 public bool m_seeIntoBannedRegion = false;
231 public int MaxUndoCount = 5; 231 public int MaxUndoCount = 5;
232 232
233 public bool SeeIntoRegion { get; set; }
234
233 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 235 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
234 public bool LoginLock = false; 236 public bool LoginLock = false;
235 237
@@ -396,10 +398,12 @@ namespace OpenSim.Region.Framework.Scenes
396 if (value) 398 if (value)
397 { 399 {
398 if (!m_active) 400 if (!m_active)
399 Start(); 401 Start(false);
400 } 402 }
401 else 403 else
402 { 404 {
405 // This appears assymetric with Start() above but is not - setting m_active = false stops the loops
406 // XXX: Possibly this should be in an explicit Stop() method for symmetry.
403 m_active = false; 407 m_active = false;
404 } 408 }
405 } 409 }
@@ -747,6 +751,7 @@ namespace OpenSim.Region.Framework.Scenes
747 m_config = config; 751 m_config = config;
748 MinFrameTime = 0.089f; 752 MinFrameTime = 0.089f;
749 MinMaintenanceTime = 1; 753 MinMaintenanceTime = 1;
754 SeeIntoRegion = true;
750 755
751 Random random = new Random(); 756 Random random = new Random();
752 757
@@ -859,9 +864,12 @@ namespace OpenSim.Region.Framework.Scenes
859 //Animation states 864 //Animation states
860 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 865 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
861 866
867 SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion);
868
869 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
870
862 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 871 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
863 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 872 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
864
865 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 873 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
866 if (RegionInfo.NonphysPrimMin > 0) 874 if (RegionInfo.NonphysPrimMin > 0)
867 { 875 {
@@ -1332,7 +1340,7 @@ namespace OpenSim.Region.Framework.Scenes
1332 Thread.Sleep(500); 1340 Thread.Sleep(500);
1333 1341
1334 // Stop all client threads. 1342 // Stop all client threads.
1335 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1343 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1336 1344
1337 m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); 1345 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1338 EventManager.TriggerSceneShuttingDown(this); 1346 EventManager.TriggerSceneShuttingDown(this);
@@ -1361,10 +1369,18 @@ namespace OpenSim.Region.Framework.Scenes
1361 } 1369 }
1362 } 1370 }
1363 1371
1372 public override void Start()
1373 {
1374 Start(true);
1375 }
1376
1364 /// <summary> 1377 /// <summary>
1365 /// Start the scene 1378 /// Start the scene
1366 /// </summary> 1379 /// </summary>
1367 public void Start() 1380 /// <param name='startScripts'>
1381 /// Start the scripts within the scene.
1382 /// </param>
1383 public void Start(bool startScripts)
1368 { 1384 {
1369 m_active = true; 1385 m_active = true;
1370 1386
@@ -1401,6 +1417,8 @@ namespace OpenSim.Region.Framework.Scenes
1401 m_heartbeatThread 1417 m_heartbeatThread
1402 = Watchdog.StartThread( 1418 = Watchdog.StartThread(
1403 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); 1419 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false);
1420
1421 StartScripts();
1404 } 1422 }
1405 1423
1406 /// <summary> 1424 /// <summary>
@@ -1557,6 +1575,8 @@ namespace OpenSim.Region.Framework.Scenes
1557 1575
1558 try 1576 try
1559 { 1577 {
1578 EventManager.TriggerRegionHeartbeatStart(this);
1579
1560 // Apply taints in terrain module to terrain in physics scene 1580 // Apply taints in terrain module to terrain in physics scene
1561 if (Frame % m_update_terrain == 0) 1581 if (Frame % m_update_terrain == 0)
1562 { 1582 {
@@ -1996,6 +2016,11 @@ namespace OpenSim.Region.Framework.Scenes
1996 2016
1997 GridRegion region = new GridRegion(RegionInfo); 2017 GridRegion region = new GridRegion(RegionInfo);
1998 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2018 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
2019 m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>",
2020 LogHeader, m_regionName,
2021 RegionInfo.RegionID,
2022 RegionInfo.RegionLocX, RegionInfo.RegionLocY,
2023 RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
1999 if (error != String.Empty) 2024 if (error != String.Empty)
2000 throw new Exception(error); 2025 throw new Exception(error);
2001 } 2026 }
@@ -2935,14 +2960,15 @@ namespace OpenSim.Region.Framework.Scenes
2935 2960
2936 #region Add/Remove Avatar Methods 2961 #region Add/Remove Avatar Methods
2937 2962
2938 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2963 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
2939 { 2964 {
2940 ScenePresence sp; 2965 ScenePresence sp;
2941 bool vialogin; 2966 bool vialogin;
2967 bool reallyNew = true;
2942 2968
2943 // Validation occurs in LLUDPServer 2969 // Validation occurs in LLUDPServer
2944 // 2970 //
2945 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with 2971 // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with
2946 // each other. In practice, this does not currently occur in the code. 2972 // each other. In practice, this does not currently occur in the code.
2947 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2973 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2948 2974
@@ -2950,9 +2976,9 @@ namespace OpenSim.Region.Framework.Scenes
2950 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point 2976 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2951 // whilst connecting). 2977 // whilst connecting).
2952 // 2978 //
2953 // It would be easier to lock across all NewUserConnection(), AddNewClient() and 2979 // It would be easier to lock across all NewUserConnection(), AddNewAgent() and
2954 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service 2980 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2955 // response in some module listening to AddNewClient()) from holding up unrelated agent calls. 2981 // response in some module listening to AddNewAgent()) from holding up unrelated agent calls.
2956 // 2982 //
2957 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all 2983 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2958 // AddNewClient() operations (though not other ops). 2984 // AddNewClient() operations (though not other ops).
@@ -2969,7 +2995,7 @@ namespace OpenSim.Region.Framework.Scenes
2969 2995
2970 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2996 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2971 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 2997 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2972 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2998 // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already
2973 // connected. 2999 // connected.
2974 if (sp == null) 3000 if (sp == null)
2975 { 3001 {
@@ -2997,16 +3023,24 @@ namespace OpenSim.Region.Framework.Scenes
2997 m_log.WarnFormat( 3023 m_log.WarnFormat(
2998 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3024 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
2999 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); 3025 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
3026 reallyNew = false;
3000 } 3027 }
3001 3028
3002 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3029 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3003 // client is for a root or child agent. 3030 // client is for a root or child agent.
3031 // XXX: This may be better set for a new client before that client is added to the client manager.
3032 // But need to know what happens in the case where a ScenePresence is already present (and if this
3033 // actually occurs).
3004 client.SceneAgent = sp; 3034 client.SceneAgent = sp;
3005 3035
3006 // Cache the user's name 3036 // This is currently also being done earlier in NewUserConnection for real users to see if this
3037 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
3038 // places. However, we still need to do it here for NPCs.
3007 CacheUserName(sp, aCircuit); 3039 CacheUserName(sp, aCircuit);
3008 3040
3009 EventManager.TriggerOnNewClient(client); 3041 if (reallyNew)
3042 EventManager.TriggerOnNewClient(client);
3043
3010 if (vialogin) 3044 if (vialogin)
3011 EventManager.TriggerOnClientLogin(client); 3045 EventManager.TriggerOnClientLogin(client);
3012 } 3046 }
@@ -3027,7 +3061,7 @@ namespace OpenSim.Region.Framework.Scenes
3027 { 3061 {
3028 string first = aCircuit.firstname, last = aCircuit.lastname; 3062 string first = aCircuit.firstname, last = aCircuit.lastname;
3029 3063
3030 if (sp.PresenceType == PresenceType.Npc) 3064 if (sp != null && sp.PresenceType == PresenceType.Npc)
3031 { 3065 {
3032 UserManagementModule.AddUser(aCircuit.AgentID, first, last); 3066 UserManagementModule.AddUser(aCircuit.AgentID, first, last);
3033 } 3067 }
@@ -3105,7 +3139,8 @@ namespace OpenSim.Region.Framework.Scenes
3105 if (sp != null) 3139 if (sp != null)
3106 { 3140 {
3107 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3141 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3108 sp.ControllingClient.Close(); 3142
3143 CloseAgent(sp.UUID, false);
3109 } 3144 }
3110 3145
3111 // BANG! SLASH! 3146 // BANG! SLASH!
@@ -3244,8 +3279,6 @@ namespace OpenSim.Region.Framework.Scenes
3244 { 3279 {
3245 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; 3280 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest;
3246 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; 3281 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest;
3247 client.OnSetStartLocationRequest += SetHomeRezPoint;
3248 client.OnRegionHandleRequest += RegionHandleRequest;
3249 } 3282 }
3250 3283
3251 public virtual void SubscribeToClientNetworkEvents(IClientAPI client) 3284 public virtual void SubscribeToClientNetworkEvents(IClientAPI client)
@@ -3371,8 +3404,6 @@ namespace OpenSim.Region.Framework.Scenes
3371 { 3404 {
3372 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; 3405 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest;
3373 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; 3406 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest;
3374 client.OnSetStartLocationRequest -= SetHomeRezPoint;
3375 client.OnRegionHandleRequest -= RegionHandleRequest;
3376 } 3407 }
3377 3408
3378 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) 3409 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client)
@@ -3498,33 +3529,6 @@ namespace OpenSim.Region.Framework.Scenes
3498 } 3529 }
3499 3530
3500 /// <summary> 3531 /// <summary>
3501 /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in
3502 /// </summary>
3503 /// <param name="remoteClient"></param>
3504 /// <param name="regionHandle"></param>
3505 /// <param name="position"></param>
3506 /// <param name="lookAt"></param>
3507 /// <param name="flags"></param>
3508 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3509 {
3510 //Add half the avatar's height so that the user doesn't fall through prims
3511 ScenePresence presence;
3512 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3513 {
3514 if (presence.Appearance != null)
3515 {
3516 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3517 }
3518 }
3519
3520 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3521 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3522 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
3523 else
3524 m_dialogModule.SendAlertToUser(remoteClient, "Set Home request Failed.");
3525 }
3526
3527 /// <summary>
3528 /// Get the avatar apperance for the given client. 3532 /// Get the avatar apperance for the given client.
3529 /// </summary> 3533 /// </summary>
3530 /// <param name="client"></param> 3534 /// <param name="client"></param>
@@ -3548,63 +3552,69 @@ namespace OpenSim.Region.Framework.Scenes
3548 } 3552 }
3549 } 3553 }
3550 3554
3551 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3555 /// <summary>
3556 /// Remove the given client from the scene.
3557 /// </summary>
3558 /// <remarks>
3559 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
3560 /// to properly operate the state machine and avoid race conditions with other close requests (such as directly
3561 /// from viewers).
3562 /// </remarks>
3563 /// <param name='agentID'>ID of agent to close</param>
3564 /// <param name='closeChildAgents'>
3565 /// Close the neighbour child agents associated with this client.
3566 /// </param>
3567 public void RemoveClient(UUID agentID, bool closeChildAgents)
3552 { 3568 {
3553// CheckHeartbeat(); 3569 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3554 bool isChildAgent = false;
3555 AgentCircuitData acd;
3556 3570
3557 lock (m_removeClientLock) 3571 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3572 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3573 // However, will keep for now just in case.
3574 if (acd == null)
3558 { 3575 {
3559 acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3576 m_log.ErrorFormat(
3577 "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name);
3560 3578
3561 if (acd == null) 3579 return;
3562 { 3580 }
3563 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); 3581 else
3564 return; 3582 {
3565 } 3583 m_authenticateHandler.RemoveCircuit(agentID);
3566 else
3567 {
3568 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3569 // simultaneously.
3570 // We also need to remove by agent ID since NPCs will have no circuit code.
3571 m_authenticateHandler.RemoveCircuit(agentID);
3572 }
3573 } 3584 }
3574 3585
3586 // TODO: Can we now remove this lock?
3575 lock (acd) 3587 lock (acd)
3576 { 3588 {
3589 bool isChildAgent = false;
3590
3577 ScenePresence avatar = GetScenePresence(agentID); 3591 ScenePresence avatar = GetScenePresence(agentID);
3578 3592
3593 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3594 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3595 // However, will keep for now just in case.
3579 if (avatar == null) 3596 if (avatar == null)
3580 { 3597 {
3581 m_log.WarnFormat( 3598 m_log.ErrorFormat(
3582 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); 3599 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3583 3600
3584 return; 3601 return;
3585 } 3602 }
3586 3603
3587 try 3604 try
3588 { 3605 {
3589 isChildAgent = avatar.IsChildAgent; 3606 isChildAgent = avatar.IsChildAgent;
3590 3607
3591 m_log.DebugFormat( 3608 m_log.DebugFormat(
3592 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3609 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3593 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); 3610 isChildAgent ? "child" : "root", avatar.Name, agentID, Name);
3594 3611
3595 // Don't do this to root agents, it's not nice for the viewer 3612 // Don't do this to root agents, it's not nice for the viewer
3596 if (closeChildAgents && isChildAgent) 3613 if (closeChildAgents && isChildAgent)
3597 { 3614 {
3598 // Tell a single agent to disconnect from the region. 3615 // Tell a single agent to disconnect from the region.
3599 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3616 // Let's do this via UDP
3600 if (eq != null) 3617 avatar.ControllingClient.SendShutdownConnectionNotice();
3601 {
3602 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3603 }
3604 else
3605 {
3606 avatar.ControllingClient.SendShutdownConnectionNotice();
3607 }
3608 } 3618 }
3609 3619
3610 // Only applies to root agents. 3620 // Only applies to root agents.
@@ -3620,16 +3630,13 @@ namespace OpenSim.Region.Framework.Scenes
3620 if (closeChildAgents && CapsModule != null) 3630 if (closeChildAgents && CapsModule != null)
3621 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode); 3631 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3622 3632
3623// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3624// // this method is doing is HORRIBLE!!!
3625 // Commented pending deletion since this method no longer appears to do anything at all
3626// avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3627
3628 if (closeChildAgents && !isChildAgent) 3633 if (closeChildAgents && !isChildAgent)
3629 { 3634 {
3630 List<ulong> regions = avatar.KnownRegionHandles; 3635 List<ulong> regions = avatar.KnownRegionHandles;
3631 regions.Remove(RegionInfo.RegionHandle); 3636 regions.Remove(RegionInfo.RegionHandle);
3632 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3637
3638 // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours.
3639 m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions);
3633 } 3640 }
3634 3641
3635 m_eventManager.TriggerClientClosed(agentID, this); 3642 m_eventManager.TriggerClientClosed(agentID, this);
@@ -3646,7 +3653,7 @@ namespace OpenSim.Region.Framework.Scenes
3646 delegate(IClientAPI client) 3653 delegate(IClientAPI client)
3647 { 3654 {
3648 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3655 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3649 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3656 try { client.SendKillObject(new List<uint> { avatar.LocalId }); }
3650 catch (NullReferenceException) { } 3657 catch (NullReferenceException) { }
3651 }); 3658 });
3652 } 3659 }
@@ -3727,7 +3734,8 @@ namespace OpenSim.Region.Framework.Scenes
3727 } 3734 }
3728 deleteIDs.Add(localID); 3735 deleteIDs.Add(localID);
3729 } 3736 }
3730 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); 3737
3738 ForEachClient(c => c.SendKillObject(deleteIDs));
3731 } 3739 }
3732 3740
3733 #endregion 3741 #endregion
@@ -3763,13 +3771,13 @@ namespace OpenSim.Region.Framework.Scenes
3763 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of 3771 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3764 /// the LLUDP stack). 3772 /// the LLUDP stack).
3765 /// </remarks> 3773 /// </remarks>
3766 /// <param name="agent">CircuitData of the agent who is connecting</param> 3774 /// <param name="acd">CircuitData of the agent who is connecting</param>
3767 /// <param name="reason">Outputs the reason for the false response on this string</param> 3775 /// <param name="reason">Outputs the reason for the false response on this string</param>
3768 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3776 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
3769 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3777 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3770 /// <returns>True if the region accepts this agent. False if it does not. False will 3778 /// <returns>True if the region accepts this agent. False if it does not. False will
3771 /// also return a reason.</returns> 3779 /// also return a reason.</returns>
3772 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3780 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup)
3773 { 3781 {
3774 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3782 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3775 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3783 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
@@ -3789,15 +3797,15 @@ namespace OpenSim.Region.Framework.Scenes
3789 m_log.DebugFormat( 3797 m_log.DebugFormat(
3790 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", 3798 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})",
3791 RegionInfo.RegionName, 3799 RegionInfo.RegionName,
3792 (agent.child ? "child" : "root"), 3800 (acd.child ? "child" : "root"),
3793 agent.firstname, 3801 acd.firstname,
3794 agent.lastname, 3802 acd.lastname,
3795 agent.AgentID, 3803 acd.AgentID,
3796 agent.circuitcode, 3804 acd.circuitcode,
3797 agent.IPAddress, 3805 acd.IPAddress,
3798 agent.Viewer, 3806 acd.Viewer,
3799 ((TPFlags)teleportFlags).ToString(), 3807 ((TPFlags)teleportFlags).ToString(),
3800 agent.startpos 3808 acd.startpos
3801 ); 3809 );
3802 3810
3803 if (!LoginsEnabled) 3811 if (!LoginsEnabled)
@@ -3815,7 +3823,7 @@ namespace OpenSim.Region.Framework.Scenes
3815 { 3823 {
3816 foreach (string viewer in m_AllowedViewers) 3824 foreach (string viewer in m_AllowedViewers)
3817 { 3825 {
3818 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3826 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3819 { 3827 {
3820 ViewerDenied = false; 3828 ViewerDenied = false;
3821 break; 3829 break;
@@ -3832,7 +3840,7 @@ namespace OpenSim.Region.Framework.Scenes
3832 { 3840 {
3833 foreach (string viewer in m_BannedViewers) 3841 foreach (string viewer in m_BannedViewers)
3834 { 3842 {
3835 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3843 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3836 { 3844 {
3837 ViewerDenied = true; 3845 ViewerDenied = true;
3838 break; 3846 break;
@@ -3844,54 +3852,129 @@ namespace OpenSim.Region.Framework.Scenes
3844 { 3852 {
3845 m_log.DebugFormat( 3853 m_log.DebugFormat(
3846 "[SCENE]: Access denied for {0} {1} using {2}", 3854 "[SCENE]: Access denied for {0} {1} using {2}",
3847 agent.firstname, agent.lastname, agent.Viewer); 3855 acd.firstname, acd.lastname, acd.Viewer);
3848 reason = "Access denied, your viewer is banned by the region owner"; 3856 reason = "Access denied, your viewer is banned by the region owner";
3849 return false; 3857 return false;
3850 } 3858 }
3851 3859
3852 ScenePresence sp = GetScenePresence(agent.AgentID); 3860 ILandObject land;
3861 ScenePresence sp;
3853 3862
3854 // If we have noo presence here or if that presence is a zombie root 3863 lock (m_removeClientLock)
3855 // presence that will be kicled, we need a new CAPS object.
3856 if (sp == null || (sp != null && !sp.IsChildAgent))
3857 { 3864 {
3858 if (CapsModule != null) 3865 sp = GetScenePresence(acd.AgentID);
3866
3867 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3868 // closed.
3869 if (sp != null && sp.IsChildAgent
3870 && (sp.LifecycleState == ScenePresenceState.Running
3871 || sp.LifecycleState == ScenePresenceState.PreRemove))
3859 { 3872 {
3860 lock (agent) 3873 m_log.DebugFormat(
3874 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3875 sp.Name, sp.LifecycleState, Name);
3876
3877 // In the case where, for example, an A B C D region layout, an avatar may
3878 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3879 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3880 //
3881 // XXX: In the end, this should not be necessary if child agents are closed without delay on
3882 // teleport, since realistically, the close request should always be processed before any other
3883 // region tried to re-establish a child agent. This is much simpler since the logic below is
3884 // vulnerable to an issue when a viewer quits a region without sending a proper logout but then
3885 // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport
3886 // flag when no teleport had taken place (and hence no close was going to come).
3887// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3888// {
3889// m_log.DebugFormat(
3890// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3891// sp.Name, Name);
3892//
3893// sp.DoNotCloseAfterTeleport = true;
3894// }
3895// else if (EntityTransferModule.IsInTransit(sp.UUID))
3896
3897 sp.LifecycleState = ScenePresenceState.Running;
3898
3899 if (EntityTransferModule.IsInTransit(sp.UUID))
3861 { 3900 {
3862 CapsModule.SetAgentCapsSeeds(agent); 3901 sp.DoNotCloseAfterTeleport = true;
3863 CapsModule.CreateCaps(agent.AgentID, agent.circuitcode); 3902
3903 m_log.DebugFormat(
3904 "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.",
3905 sp.Name, Name);
3864 } 3906 }
3865 } 3907 }
3866 } 3908 }
3867 3909
3910 // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will
3911 // allow unpredictable things to happen.
3868 if (sp != null) 3912 if (sp != null)
3869 { 3913 {
3870 if (!sp.IsChildAgent) 3914 const int polls = 10;
3915 const int pollInterval = 1000;
3916 int pollsLeft = polls;
3917
3918 while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0)
3919 Thread.Sleep(pollInterval);
3920
3921 if (sp.LifecycleState == ScenePresenceState.Removing)
3871 { 3922 {
3872 // We have a zombie from a crashed session.
3873 // Or the same user is trying to be root twice here, won't work.
3874 // Kill it.
3875 m_log.WarnFormat( 3923 m_log.WarnFormat(
3876 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3924 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3877 sp.Name, sp.UUID, RegionInfo.RegionName); 3925 sp.Name, Name, polls * pollInterval / 1000);
3878 3926
3879 sp.ControllingClient.Close(true, true); 3927 return false;
3880 sp = null; 3928 }
3929 else if (polls != pollsLeft)
3930 {
3931 m_log.DebugFormat(
3932 "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.",
3933 sp.Name, Name, polls * pollInterval / 1000);
3881 } 3934 }
3882 } 3935 }
3883 3936
3884 lock (agent) 3937 // TODO: can we remove this lock?
3938 lock (acd)
3885 { 3939 {
3886 //On login test land permisions 3940 if (sp != null && !sp.IsChildAgent)
3941 {
3942 // We have a root agent. Is it in transit?
3943 if (!EntityTransferModule.IsInTransit(sp.UUID))
3944 {
3945 // We have a zombie from a crashed session.
3946 // Or the same user is trying to be root twice here, won't work.
3947 // Kill it.
3948 m_log.WarnFormat(
3949 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3950 sp.Name, sp.UUID, RegionInfo.RegionName);
3951
3952 if (sp.ControllingClient != null)
3953 CloseAgent(sp.UUID, true);
3954
3955 sp = null;
3956 }
3957 //else
3958 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3959 }
3960
3961 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
3962 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3963 // If the checks fail, we remove the circuit.
3964 acd.teleportFlags = teleportFlags;
3965 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3966
3967 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3968
3969 // On login test land permisions
3887 if (vialogin) 3970 if (vialogin)
3888 { 3971 {
3889 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3972 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3890 if (cache != null) 3973 if (cache != null)
3891 cache.Remove(agent.firstname + " " + agent.lastname); 3974 cache.Remove(acd.firstname + " " + acd.lastname);
3892 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) 3975 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3893 { 3976 {
3894 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3977 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3895 return false; 3978 return false;
3896 } 3979 }
3897 } 3980 }
@@ -3902,84 +3985,97 @@ namespace OpenSim.Region.Framework.Scenes
3902 { 3985 {
3903 try 3986 try
3904 { 3987 {
3905 if (!VerifyUserPresence(agent, out reason)) 3988 if (!VerifyUserPresence(acd, out reason))
3989 {
3990 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3906 return false; 3991 return false;
3907 } catch (Exception e) 3992 }
3993 }
3994 catch (Exception e)
3908 { 3995 {
3909 m_log.ErrorFormat( 3996 m_log.ErrorFormat(
3910 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3997 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3998
3999 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3911 return false; 4000 return false;
3912 } 4001 }
3913 } 4002 }
3914 4003
3915 try 4004 try
3916 { 4005 {
3917 // Always check estate if this is a login. Always 4006 if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
3918 // check if banned regions are to be blacked out.
3919 if (vialogin || (!m_seeIntoBannedRegion))
3920 { 4007 {
3921 if (!AuthorizeUser(agent, out reason)) 4008 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3922 { 4009 return false;
3923 return false;
3924 }
3925 } 4010 }
3926 } 4011 }
3927 catch (Exception e) 4012 catch (Exception e)
3928 { 4013 {
3929 m_log.ErrorFormat( 4014 m_log.ErrorFormat(
3930 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 4015 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
4016
4017 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3931 return false; 4018 return false;
3932 } 4019 }
3933 4020
3934 m_log.InfoFormat( 4021 m_log.InfoFormat(
3935 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 4022 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3936 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, 4023 Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
3937 agent.AgentID, agent.circuitcode); 4024 acd.AgentID, acd.circuitcode);
3938 4025
4026 if (CapsModule != null)
4027 {
4028 CapsModule.SetAgentCapsSeeds(acd);
4029 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4030 }
3939 } 4031 }
3940 else 4032 else
3941 { 4033 {
3942 // Let the SP know how we got here. This has a lot of interesting 4034 // Let the SP know how we got here. This has a lot of interesting
3943 // uses down the line. 4035 // uses down the line.
3944 sp.TeleportFlags = (TPFlags)teleportFlags; 4036 sp.TeleportFlags = (TPFlags)teleportFlags;
3945 4037
3946 if (sp.IsChildAgent) 4038 if (sp.IsChildAgent)
3947 { 4039 {
3948 m_log.DebugFormat( 4040 m_log.DebugFormat(
3949 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4041 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3950 agent.AgentID, RegionInfo.RegionName); 4042 acd.AgentID, RegionInfo.RegionName);
3951 4043
3952 sp.AdjustKnownSeeds(); 4044 sp.AdjustKnownSeeds();
3953 4045
3954 if (CapsModule != null) 4046 if (CapsModule != null)
3955 CapsModule.SetAgentCapsSeeds(agent); 4047 {
4048 CapsModule.SetAgentCapsSeeds(acd);
4049 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4050 }
3956 } 4051 }
3957 } 4052 }
3958 }
3959 4053
3960 // In all cases, add or update the circuit data with the new agent circuit data and teleport flags 4054 // Try caching an incoming user name much earlier on to see if this helps with an issue
3961 agent.teleportFlags = teleportFlags; 4055 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName
3962 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 4056 // request for the HG avatar appears to trigger before the user name is cached.
4057 CacheUserName(null, acd);
4058 }
3963 4059
3964 if (CapsModule != null) 4060 if (CapsModule != null)
3965 { 4061 {
3966 CapsModule.ActivateCaps(agent.circuitcode); 4062 CapsModule.ActivateCaps(acd.circuitcode);
3967 } 4063 }
3968 4064
3969 if (vialogin) 4065 if (vialogin)
3970 { 4066 {
3971// CleanDroppedAttachments(); 4067// CleanDroppedAttachments();
3972 4068
3973 if (TestBorderCross(agent.startpos, Cardinals.E)) 4069 if (TestBorderCross(acd.startpos, Cardinals.E))
3974 { 4070 {
3975 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 4071 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3976 agent.startpos.X = crossedBorder.BorderLine.Z - 1; 4072 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3977 } 4073 }
3978 4074
3979 if (TestBorderCross(agent.startpos, Cardinals.N)) 4075 if (TestBorderCross(acd.startpos, Cardinals.N))
3980 { 4076 {
3981 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); 4077 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
3982 agent.startpos.Y = crossedBorder.BorderLine.Z - 1; 4078 acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
3983 } 4079 }
3984 4080
3985 //Mitigate http://opensimulator.org/mantis/view.php?id=3522 4081 //Mitigate http://opensimulator.org/mantis/view.php?id=3522
@@ -3989,68 +4085,88 @@ namespace OpenSim.Region.Framework.Scenes
3989 { 4085 {
3990 lock (EastBorders) 4086 lock (EastBorders)
3991 { 4087 {
3992 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4088 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
3993 { 4089 {
3994 m_log.Warn("FIX AGENT POSITION"); 4090 m_log.Warn("FIX AGENT POSITION");
3995 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4091 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3996 if (agent.startpos.Z > 720) 4092 if (acd.startpos.Z > 720)
3997 agent.startpos.Z = 720; 4093 acd.startpos.Z = 720;
3998 } 4094 }
3999 } 4095 }
4000 lock (NorthBorders) 4096 lock (NorthBorders)
4001 { 4097 {
4002 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4098 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4003 { 4099 {
4004 m_log.Warn("FIX Agent POSITION"); 4100 m_log.Warn("FIX Agent POSITION");
4005 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4101 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4006 if (agent.startpos.Z > 720) 4102 if (acd.startpos.Z > 720)
4007 agent.startpos.Z = 720; 4103 acd.startpos.Z = 720;
4008 } 4104 }
4009 } 4105 }
4010 } else 4106 } else
4011 { 4107 {
4012 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4108 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
4013 { 4109 {
4014 m_log.Warn("FIX AGENT POSITION"); 4110 m_log.Warn("FIX AGENT POSITION");
4015 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4111 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
4016 if (agent.startpos.Z > 720) 4112 if (acd.startpos.Z > 720)
4017 agent.startpos.Z = 720; 4113 acd.startpos.Z = 720;
4018 } 4114 }
4019 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4115 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4020 { 4116 {
4021 m_log.Warn("FIX Agent POSITION"); 4117 m_log.Warn("FIX Agent POSITION");
4022 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4118 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4023 if (agent.startpos.Z > 720) 4119 if (acd.startpos.Z > 720)
4024 agent.startpos.Z = 720; 4120 acd.startpos.Z = 720;
4025 } 4121 }
4026 } 4122 }
4027 4123
4124// m_log.DebugFormat(
4125// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
4126// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4127
4028 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags 4128 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
4029 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && 4129 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
4030 RegionInfo.EstateSettings.AllowDirectTeleport == false && 4130 RegionInfo.EstateSettings.AllowDirectTeleport == false &&
4031 !viahome && !godlike) 4131 !viahome && !godlike)
4032 { 4132 {
4033 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); 4133 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
4034 // Can have multiple SpawnPoints 4134
4035 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); 4135 if (telehub != null)
4036 if (spawnpoints.Count > 1)
4037 { 4136 {
4038 // We have multiple SpawnPoints, Route the agent to a random or sequential one 4137 // Can have multiple SpawnPoints
4039 if (SpawnPointRouting == "random") 4138 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
4040 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 4139 if (spawnpoints.Count > 1)
4041 telehub.AbsolutePosition, 4140 {
4042 telehub.GroupRotation 4141 // We have multiple SpawnPoints, Route the agent to a random or sequential one
4043 ); 4142 if (SpawnPointRouting == "random")
4143 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
4144 telehub.AbsolutePosition,
4145 telehub.GroupRotation
4146 );
4147 else
4148 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
4149 telehub.AbsolutePosition,
4150 telehub.GroupRotation
4151 );
4152 }
4153 else if (spawnpoints.Count == 1)
4154 {
4155 // We have a single SpawnPoint and will route the agent to it
4156 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4157 }
4044 else 4158 else
4045 agent.startpos = spawnpoints[SpawnPoint()].GetLocation( 4159 {
4046 telehub.AbsolutePosition, 4160 m_log.DebugFormat(
4047 telehub.GroupRotation 4161 "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
4048 ); 4162 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4163 }
4049 } 4164 }
4050 else 4165 else
4051 { 4166 {
4052 // We have a single SpawnPoint and will route the agent to it 4167 m_log.DebugFormat(
4053 agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4168 "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
4169 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4054 } 4170 }
4055 4171
4056 return true; 4172 return true;
@@ -4063,7 +4179,7 @@ namespace OpenSim.Region.Framework.Scenes
4063 { 4179 {
4064 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4180 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
4065 { 4181 {
4066 agent.startpos = land.LandData.UserLocation; 4182 acd.startpos = land.LandData.UserLocation;
4067 } 4183 }
4068 } 4184 }
4069 */// This is now handled properly in ScenePresence.MakeRootAgent 4185 */// This is now handled properly in ScenePresence.MakeRootAgent
@@ -4158,7 +4274,7 @@ namespace OpenSim.Region.Framework.Scenes
4158 /// <param name="reason">outputs the reason to this string</param> 4274 /// <param name="reason">outputs the reason to this string</param>
4159 /// <returns>True if the region accepts this agent. False if it does not. False will 4275 /// <returns>True if the region accepts this agent. False if it does not. False will
4160 /// also return a reason.</returns> 4276 /// also return a reason.</returns>
4161 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 4277 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
4162 { 4278 {
4163 reason = String.Empty; 4279 reason = String.Empty;
4164 4280
@@ -4177,67 +4293,75 @@ namespace OpenSim.Region.Framework.Scenes
4177 } 4293 }
4178 } 4294 }
4179 4295
4180 if (RegionInfo.EstateSettings != null) 4296 // We only test the things below when we want to cut off
4297 // child agents from being present in the scene for which their root
4298 // agent isn't allowed. Otherwise, we allow child agents. The test for
4299 // the root is done elsewhere (QueryAccess)
4300 if (!bypassAccessControl)
4181 { 4301 {
4182 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0)) 4302 if (RegionInfo.EstateSettings != null)
4183 { 4303 {
4184 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4304 int flags = GetUserFlags(agent.AgentID);
4185 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4305 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4186 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 4306 {
4187 RegionInfo.RegionName); 4307 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4188 return false; 4308 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4309 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4310 RegionInfo.RegionName);
4311 return false;
4312 }
4189 } 4313 }
4190 } 4314 else
4191 else
4192 {
4193 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4194 }
4195
4196 List<UUID> agentGroups = new List<UUID>();
4197
4198 if (m_groupsModule != null)
4199 {
4200 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4201
4202 if (GroupMembership != null)
4203 { 4315 {
4204 for (int i = 0; i < GroupMembership.Length; i++) 4316 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4205 agentGroups.Add(GroupMembership[i].GroupID);
4206 } 4317 }
4207 else 4318
4319 List<UUID> agentGroups = new List<UUID>();
4320
4321 if (m_groupsModule != null)
4208 { 4322 {
4209 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); 4323 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4324
4325 if (GroupMembership != null)
4326 {
4327 for (int i = 0; i < GroupMembership.Length; i++)
4328 agentGroups.Add(GroupMembership[i].GroupID);
4329 }
4330 else
4331 {
4332 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4333 }
4210 } 4334 }
4211 }
4212 4335
4213 bool groupAccess = false; 4336 bool groupAccess = false;
4214 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; 4337 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4215 4338
4216 if (estateGroups != null) 4339 if (estateGroups != null)
4217 {
4218 foreach (UUID group in estateGroups)
4219 { 4340 {
4220 if (agentGroups.Contains(group)) 4341 foreach (UUID group in estateGroups)
4221 { 4342 {
4222 groupAccess = true; 4343 if (agentGroups.Contains(group))
4223 break; 4344 {
4345 groupAccess = true;
4346 break;
4347 }
4224 } 4348 }
4225 } 4349 }
4226 } 4350 else
4227 else 4351 {
4228 { 4352 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4229 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 4353 }
4230 }
4231 4354
4232 if (!RegionInfo.EstateSettings.PublicAccess && 4355 if (!RegionInfo.EstateSettings.PublicAccess &&
4233 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4356 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) &&
4234 !groupAccess) 4357 !groupAccess)
4235 { 4358 {
4236 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4359 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate",
4237 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4360 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4238 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 4361 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
4239 RegionInfo.RegionName); 4362 RegionInfo.RegionName);
4240 return false; 4363 return false;
4364 }
4241 } 4365 }
4242 4366
4243 // TODO: estate/region settings are not properly hooked up 4367 // TODO: estate/region settings are not properly hooked up
@@ -4362,13 +4486,11 @@ namespace OpenSim.Region.Framework.Scenes
4362 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4486 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
4363 /// Appearance, animations, position, etc.</param> 4487 /// Appearance, animations, position, etc.</param>
4364 /// <returns>true if we handled it.</returns> 4488 /// <returns>true if we handled it.</returns>
4365 public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData) 4489 public virtual bool IncomingUpdateChildAgent(AgentData cAgentData)
4366 { 4490 {
4367 m_log.DebugFormat( 4491 m_log.DebugFormat(
4368 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4492 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4369 4493
4370 // XPTO: if this agent is not allowed here as root, always return false
4371
4372 // We have to wait until the viewer contacts this region after receiving EAC. 4494 // We have to wait until the viewer contacts this region after receiving EAC.
4373 // That calls AddNewClient, which finally creates the ScenePresence 4495 // That calls AddNewClient, which finally creates the ScenePresence
4374 int flags = GetUserFlags(cAgentData.AgentID); 4496 int flags = GetUserFlags(cAgentData.AgentID);
@@ -4382,7 +4504,7 @@ namespace OpenSim.Region.Framework.Scenes
4382 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4504 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
4383 if (nearestParcel == null) 4505 if (nearestParcel == null)
4384 { 4506 {
4385 m_log.DebugFormat( 4507 m_log.InfoFormat(
4386 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", 4508 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel",
4387 cAgentData.AgentID, RegionInfo.RegionName); 4509 cAgentData.AgentID, RegionInfo.RegionName);
4388 4510
@@ -4390,13 +4512,44 @@ namespace OpenSim.Region.Framework.Scenes
4390 } 4512 }
4391 4513
4392 // We have to wait until the viewer contacts this region 4514 // We have to wait until the viewer contacts this region
4393 // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send 4515 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
4394 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. 4516 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4395 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4517 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4518 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4396 4519
4397 if (childAgentUpdate != null) 4520 if (sp != null)
4398 { 4521 {
4399 childAgentUpdate.ChildAgentDataUpdate(cAgentData); 4522 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4523 {
4524 m_log.WarnFormat(
4525 "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
4526 sp.UUID, cAgentData.SessionID);
4527
4528 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4529 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4530 }
4531
4532 sp.UpdateChildAgent(cAgentData);
4533
4534 int ntimes = 20;
4535 if (cAgentData.SenderWantsToWaitForRoot)
4536 {
4537 while (sp.IsChildAgent && ntimes-- > 0)
4538 Thread.Sleep(1000);
4539
4540 if (sp.IsChildAgent)
4541 m_log.WarnFormat(
4542 "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}",
4543 sp.Name, sp.UUID, Name);
4544 else
4545 m_log.InfoFormat(
4546 "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits",
4547 sp.Name, sp.UUID, Name, 20 - ntimes);
4548
4549 if (sp.IsChildAgent)
4550 return false;
4551 }
4552
4400 return true; 4553 return true;
4401 } 4554 }
4402 4555
@@ -4409,12 +4562,17 @@ namespace OpenSim.Region.Framework.Scenes
4409 /// </summary> 4562 /// </summary>
4410 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4563 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
4411 /// <returns>true if we handled it.</returns> 4564 /// <returns>true if we handled it.</returns>
4412 public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) 4565 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4413 { 4566 {
4414 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); 4567 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName);
4415 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4568 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
4416 if (childAgentUpdate != null) 4569 if (childAgentUpdate != null)
4417 { 4570 {
4571// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4572// // Only warn for now
4573// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4574// childAgentUpdate.UUID, cAgentData.SessionID);
4575
4418 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4576 // I can't imagine *yet* why we would get an update if the agent is a root agent..
4419 // however to avoid a race condition crossing borders.. 4577 // however to avoid a race condition crossing borders..
4420 if (childAgentUpdate.IsChildAgent) 4578 if (childAgentUpdate.IsChildAgent)
@@ -4424,7 +4582,7 @@ namespace OpenSim.Region.Framework.Scenes
4424 uint tRegionX = RegionInfo.RegionLocX; 4582 uint tRegionX = RegionInfo.RegionLocX;
4425 uint tRegionY = RegionInfo.RegionLocY; 4583 uint tRegionY = RegionInfo.RegionLocY;
4426 //Send Data to ScenePresence 4584 //Send Data to ScenePresence
4427 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); 4585 childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4428 // Not Implemented: 4586 // Not Implemented:
4429 //TODO: Do we need to pass the message on to one of our neighbors? 4587 //TODO: Do we need to pass the message on to one of our neighbors?
4430 } 4588 }
@@ -4451,35 +4609,99 @@ namespace OpenSim.Region.Framework.Scenes
4451 m_log.WarnFormat( 4609 m_log.WarnFormat(
4452 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", 4610 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
4453 agentID, RegionInfo.RegionName); 4611 agentID, RegionInfo.RegionName);
4454// else
4455// m_log.DebugFormat(
4456// "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits",
4457// sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes);
4458 4612
4459 return sp; 4613 return sp;
4460 } 4614 }
4461 4615
4462 public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) 4616 /// <summary>
4617 /// Authenticated close (via network)
4618 /// </summary>
4619 /// <param name="agentID"></param>
4620 /// <param name="force"></param>
4621 /// <param name="auth_token"></param>
4622 /// <returns></returns>
4623 public bool CloseAgent(UUID agentID, bool force, string auth_token)
4463 { 4624 {
4464 agent = null; 4625 //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token);
4465 ScenePresence sp = GetScenePresence(id); 4626
4466 if ((sp != null) && (!sp.IsChildAgent)) 4627 // Check that the auth_token is valid
4628 AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID);
4629
4630 if (acd == null)
4467 { 4631 {
4468 sp.IsChildAgent = true; 4632 m_log.DebugFormat(
4469 return sp.CopyAgent(out agent); 4633 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4634 agentID, Name);
4635
4636 return false;
4637 }
4638
4639 if (acd.SessionID.ToString() == auth_token)
4640 {
4641 return CloseAgent(agentID, force);
4642 }
4643 else
4644 {
4645 m_log.WarnFormat(
4646 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4647 agentID, auth_token, Name);
4470 } 4648 }
4471 4649
4472 return false; 4650 return false;
4473 } 4651 }
4474 4652
4475 public bool IncomingCloseAgent(UUID agentID) 4653// public bool IncomingCloseAgent(UUID agentID)
4476 { 4654// {
4477 return IncomingCloseAgent(agentID, false); 4655// return IncomingCloseAgent(agentID, false);
4478 } 4656// }
4479 4657
4480 public bool IncomingCloseChildAgent(UUID agentID) 4658// public bool IncomingCloseChildAgent(UUID agentID)
4659// {
4660// return IncomingCloseAgent(agentID, true);
4661// }
4662
4663 /// <summary>
4664 /// Tell a single client to prepare to close.
4665 /// </summary>
4666 /// <remarks>
4667 /// This should only be called if we may close the client but there will be some delay in so doing. Meant for
4668 /// internal use - other callers should almost certainly called CloseClient().
4669 /// </remarks>
4670 /// <param name="sp"></param>
4671 /// <returns>true if pre-close state notification was successful. false if the agent
4672 /// was not in a state where it could transition to pre-close.</returns>
4673 public bool IncomingPreCloseClient(ScenePresence sp)
4481 { 4674 {
4482 return IncomingCloseAgent(agentID, true); 4675 lock (m_removeClientLock)
4676 {
4677 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4678 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4679 // want to obey this close since C may have renewed the child agent lease on B.
4680 if (sp.DoNotCloseAfterTeleport)
4681 {
4682 m_log.DebugFormat(
4683 "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4684 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4685
4686 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4687 sp.DoNotCloseAfterTeleport = false;
4688
4689 return false;
4690 }
4691
4692 if (sp.LifecycleState != ScenePresenceState.Running)
4693 {
4694 m_log.DebugFormat(
4695 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4696 sp.Name, Name, sp.LifecycleState);
4697
4698 return false;
4699 }
4700
4701 sp.LifecycleState = ScenePresenceState.PreRemove;
4702
4703 return true;
4704 }
4483 } 4705 }
4484 4706
4485 /// <summary> 4707 /// <summary>
@@ -4490,18 +4712,57 @@ namespace OpenSim.Region.Framework.Scenes
4490 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to 4712 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4491 /// force unless you are absolutely sure that the agent is dead and a normal close is not working. 4713 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4492 /// </param> 4714 /// </param>
4493 public bool IncomingCloseAgent(UUID agentID, bool force) 4715 public override bool CloseAgent(UUID agentID, bool force)
4494 { 4716 {
4495 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4717 ScenePresence sp;
4496 4718
4497 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4719 lock (m_removeClientLock)
4498 if (presence != null) 4720 {
4721 sp = GetScenePresence(agentID);
4722
4723 if (sp == null)
4724 {
4725 m_log.DebugFormat(
4726 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4727 agentID, Name);
4728
4729 return false;
4730 }
4731
4732 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4733 {
4734 m_log.DebugFormat(
4735 "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}",
4736 sp.Name, Name, sp.LifecycleState);
4737
4738 return false;
4739 }
4740
4741 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4742 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4743 // want to obey this close since C may have renewed the child agent lease on B.
4744 if (sp.DoNotCloseAfterTeleport)
4745 {
4746 m_log.DebugFormat(
4747 "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4748 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4749
4750 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4751 sp.DoNotCloseAfterTeleport = false;
4752
4753 return false;
4754 }
4755
4756 sp.LifecycleState = ScenePresenceState.Removing;
4757 }
4758
4759 if (sp != null)
4499 { 4760 {
4500 presence.ControllingClient.Close(force, force); 4761 sp.ControllingClient.Close(force, force);
4501 return true; 4762 return true;
4502 } 4763 }
4503 4764
4504 // Agent not here 4765 // Agent not here
4505 return false; 4766 return false;
4506 } 4767 }
4507 4768
@@ -5091,21 +5352,6 @@ namespace OpenSim.Region.Framework.Scenes
5091 5352
5092 #endregion 5353 #endregion
5093 5354
5094 public void RegionHandleRequest(IClientAPI client, UUID regionID)
5095 {
5096 ulong handle = 0;
5097 if (regionID == RegionInfo.RegionID)
5098 handle = RegionInfo.RegionHandle;
5099 else
5100 {
5101 GridRegion r = GridService.GetRegionByUUID(UUID.Zero, regionID);
5102 if (r != null)
5103 handle = r.RegionHandle;
5104 }
5105
5106 if (handle != 0)
5107 client.SendRegionHandle(regionID, handle);
5108 }
5109 5355
5110// Commented pending deletion since this method no longer appears to do anything at all 5356// Commented pending deletion since this method no longer appears to do anything at all
5111// public bool NeedSceneCacheClear(UUID agentID) 5357// public bool NeedSceneCacheClear(UUID agentID)
@@ -5657,12 +5903,12 @@ Environment.Exit(1);
5657 List<SceneObjectGroup> objects, 5903 List<SceneObjectGroup> objects,
5658 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 5904 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
5659 { 5905 {
5660 minX = 256; 5906 minX = float.MaxValue;
5661 maxX = -256; 5907 maxX = float.MinValue;
5662 minY = 256; 5908 minY = float.MaxValue;
5663 maxY = -256; 5909 maxY = float.MinValue;
5664 minZ = 8192; 5910 minZ = float.MaxValue;
5665 maxZ = -256; 5911 maxZ = float.MinValue;
5666 5912
5667 List<Vector3> offsets = new List<Vector3>(); 5913 List<Vector3> offsets = new List<Vector3>();
5668 5914
@@ -5802,17 +6048,6 @@ Environment.Exit(1);
5802 { 6048 {
5803 reason = "You are banned from the region"; 6049 reason = "You are banned from the region";
5804 6050
5805 if (EntityTransferModule.IsInTransit(agentID))
5806 {
5807 reason = "Agent is still in transit from this region";
5808
5809 m_log.WarnFormat(
5810 "[SCENE]: Denying agent {0} entry into {1} since region still has them registered as in transit",
5811 agentID, RegionInfo.RegionName);
5812
5813 return false;
5814 }
5815
5816 if (Permissions.IsGod(agentID)) 6051 if (Permissions.IsGod(agentID))
5817 { 6052 {
5818 reason = String.Empty; 6053 reason = String.Empty;
@@ -5862,9 +6097,9 @@ Environment.Exit(1);
5862 6097
5863 try 6098 try
5864 { 6099 {
5865 if (!AuthorizeUser(aCircuit, out reason)) 6100 if (!AuthorizeUser(aCircuit, false, out reason))
5866 { 6101 {
5867 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6102 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5868 return false; 6103 return false;
5869 } 6104 }
5870 } 6105 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 74c9582..08e26c5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -42,7 +42,8 @@ namespace OpenSim.Region.Framework.Scenes
42{ 42{
43 public abstract class SceneBase : IScene 43 public abstract class SceneBase : IScene
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 protected static readonly string LogHeader = "[SCENE]";
46 47
47 #region Events 48 #region Events
48 49
@@ -217,8 +218,9 @@ namespace OpenSim.Region.Framework.Scenes
217 218
218 #region Add/Remove Agent/Avatar 219 #region Add/Remove Agent/Avatar
219 220
220 public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); 221 public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
221 public abstract void RemoveClient(UUID agentID, bool closeChildAgents); 222
223 public abstract bool CloseAgent(UUID agentID, bool force);
222 224
223 public bool TryGetScenePresence(UUID agentID, out object scenePresence) 225 public bool TryGetScenePresence(UUID agentID, out object scenePresence)
224 { 226 {
@@ -562,6 +564,10 @@ namespace OpenSim.Region.Framework.Scenes
562 get { return false; } 564 get { return false; }
563 } 565 }
564 566
567 public virtual void Start()
568 {
569 }
570
565 public void Restart() 571 public void Restart()
566 { 572 {
567 // This has to be here to fire the event 573 // This has to be here to fire the event
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 775a4c2..52f46f2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes
200 /// This Closes child agents on neighboring regions 200 /// This Closes child agents on neighboring regions
201 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 201 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
202 /// </summary> 202 /// </summary>
203 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle) 203 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token)
204 { 204 {
205 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 205 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
206 206
@@ -209,23 +209,25 @@ namespace OpenSim.Region.Framework.Scenes
209 Utils.LongToUInts(regionHandle, out x, out y); 209 Utils.LongToUInts(regionHandle, out x, out y);
210 210
211 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 211 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
212 m_scene.SimulationService.CloseChildAgent(destination, agentID);
213 }
214 212
215 private void SendCloseChildAgentCompleted(IAsyncResult iar) 213 m_log.DebugFormat(
216 { 214 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName);
217 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState; 215
218 icon.EndInvoke(iar); 216 m_scene.SimulationService.CloseAgent(destination, agentID, auth_token);
219 } 217 }
220 218
221 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 219 /// <summary>
220 /// Closes a child agents in a collection of regions. Does so asynchronously
221 /// so that the caller doesn't wait.
222 /// </summary>
223 /// <param name="agentID"></param>
224 /// <param name="regionslst"></param>
225 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst)
222 { 226 {
223 foreach (ulong handle in regionslst) 227 foreach (ulong handle in regionslst)
224 { 228 {
225 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync; 229 ulong handleCopy = handle;
226 d.BeginInvoke(agentID, handle, 230 Util.FireAndForget((o) => { SendCloseChildAgent(agentID, handleCopy, auth_code); });
227 SendCloseChildAgentCompleted,
228 d);
229 } 231 }
230 } 232 }
231 233
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e599e90..b0f8991 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -631,40 +631,16 @@ namespace OpenSim.Region.Framework.Scenes
631 protected internal ScenePresence CreateAndAddChildScenePresence( 631 protected internal ScenePresence CreateAndAddChildScenePresence(
632 IClientAPI client, AvatarAppearance appearance, PresenceType type) 632 IClientAPI client, AvatarAppearance appearance, PresenceType type)
633 { 633 {
634 ScenePresence newAvatar = null;
635
636 // ScenePresence always defaults to child agent 634 // ScenePresence always defaults to child agent
637 newAvatar = new ScenePresence(client, m_parentScene, appearance, type); 635 ScenePresence presence = new ScenePresence(client, m_parentScene, appearance, type);
638
639 AddScenePresence(newAvatar);
640
641 return newAvatar;
642 }
643
644 /// <summary>
645 /// Add a presence to the scene
646 /// </summary>
647 /// <param name="presence"></param>
648 protected internal void AddScenePresence(ScenePresence presence)
649 {
650 // Always a child when added to the scene
651 bool child = presence.IsChildAgent;
652
653 if (child)
654 {
655 m_numChildAgents++;
656 }
657 else
658 {
659 m_numRootAgents++;
660 presence.AddToPhysicalScene(false);
661 }
662 636
663 Entities[presence.UUID] = presence; 637 Entities[presence.UUID] = presence;
664 638
665 m_scenePresencesLock.EnterWriteLock(); 639 m_scenePresencesLock.EnterWriteLock();
666 try 640 try
667 { 641 {
642 m_numChildAgents++;
643
668 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 644 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
669 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 645 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
670 646
@@ -675,7 +651,7 @@ namespace OpenSim.Region.Framework.Scenes
675 } 651 }
676 else 652 else
677 { 653 {
678 // Remember the old presene reference from the dictionary 654 // Remember the old presence reference from the dictionary
679 ScenePresence oldref = newmap[presence.UUID]; 655 ScenePresence oldref = newmap[presence.UUID];
680 // Replace the presence reference in the dictionary with the new value 656 // Replace the presence reference in the dictionary with the new value
681 newmap[presence.UUID] = presence; 657 newmap[presence.UUID] = presence;
@@ -691,6 +667,8 @@ namespace OpenSim.Region.Framework.Scenes
691 { 667 {
692 m_scenePresencesLock.ExitWriteLock(); 668 m_scenePresencesLock.ExitWriteLock();
693 } 669 }
670
671 return presence;
694 } 672 }
695 673
696 /// <summary> 674 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index c70342f..c5c083a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -420,29 +420,6 @@ namespace OpenSim.Region.Framework.Scenes
420 return false; 420 return false;
421 } 421 }
422 422
423 /// <summary>
424 /// Set the debug packet level on each current scene. This level governs which packets are printed out to the
425 /// console.
426 /// </summary>
427 /// <param name="newDebug"></param>
428 /// <param name="name">Name of avatar to debug</param>
429 public void SetDebugPacketLevelOnCurrentScene(int newDebug, string name)
430 {
431 ForEachSelectedScene(scene =>
432 scene.ForEachScenePresence(sp =>
433 {
434 if (name == null || sp.Name == name)
435 {
436 m_log.DebugFormat(
437 "Packet debug for {0} ({1}) set to {2}",
438 sp.Name, sp.IsChildAgent ? "child" : "root", newDebug);
439
440 sp.ControllingClient.DebugPacketLevel = newDebug;
441 }
442 })
443 );
444 }
445
446 public List<ScenePresence> GetCurrentSceneAvatars() 423 public List<ScenePresence> GetCurrentSceneAvatars()
447 { 424 {
448 List<ScenePresence> avatars = new List<ScenePresence>(); 425 List<ScenePresence> avatars = new List<ScenePresence>();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f8624e7..8c50a81 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -67,6 +67,12 @@ namespace OpenSim.Region.Framework.Scenes
67 { 67 {
68 int scriptsStarted = 0; 68 int scriptsStarted = 0;
69 69
70 if (m_scene == null)
71 {
72 m_log.DebugFormat("[PRIM INVENTORY]: m_scene is null. Unable to create script instances");
73 return 0;
74 }
75
70 // Don't start scripts if they're turned off in the region! 76 // Don't start scripts if they're turned off in the region!
71 if (!m_scene.RegionInfo.RegionSettings.DisableScripts) 77 if (!m_scene.RegionInfo.RegionSettings.DisableScripts)
72 { 78 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 86f60bb..cfa862e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -111,6 +111,9 @@ namespace OpenSim.Region.Framework.Scenes
111 STATUS_ROTATE_Z = 0x008, 111 STATUS_ROTATE_Z = 0x008,
112 } 112 }
113 113
114 // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm
115 public static readonly uint SLAM = 16;
116
114 // private PrimCountTaintedDelegate handlerPrimCountTainted = null; 117 // private PrimCountTaintedDelegate handlerPrimCountTainted = null;
115 118
116 /// <summary> 119 /// <summary>
@@ -506,9 +509,7 @@ namespace OpenSim.Region.Framework.Scenes
506 { 509 {
507 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); 510 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
508 } 511 }
509 512
510
511
512 private struct avtocrossInfo 513 private struct avtocrossInfo
513 { 514 {
514 public ScenePresence av; 515 public ScenePresence av;
@@ -660,12 +661,6 @@ namespace OpenSim.Region.Framework.Scenes
660 } 661 }
661 } 662 }
662 663
663/* don't see the need but worse don't see where is restored to false if things stay in
664 foreach (SceneObjectPart part in m_parts.GetArray())
665 {
666 part.IgnoreUndoUpdate = true;
667 }
668 */
669 if (RootPart.GetStatusSandbox()) 664 if (RootPart.GetStatusSandbox())
670 { 665 {
671 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 666 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -751,7 +746,6 @@ namespace OpenSim.Region.Framework.Scenes
751 } 746 }
752 747
753 agent.ParentUUID = UUID.Zero; 748 agent.ParentUUID = UUID.Zero;
754
755// agent.Reset(); 749// agent.Reset();
756// else // Not successful 750// else // Not successful
757// agent.RestoreInCurrentScene(); 751// agent.RestoreInCurrentScene();
@@ -1667,7 +1661,8 @@ namespace OpenSim.Region.Framework.Scenes
1667 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 1661 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1668 if (avatar == null) 1662 if (avatar == null)
1669 return; 1663 return;
1670 1664 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
1665 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
1671 avatar.RemoveAttachment(this); 1666 avatar.RemoveAttachment(this);
1672 1667
1673 Vector3 detachedpos = new Vector3(127f,127f,127f); 1668 Vector3 detachedpos = new Vector3(127f,127f,127f);
@@ -1868,11 +1863,11 @@ namespace OpenSim.Region.Framework.Scenes
1868 /// <summary> 1863 /// <summary>
1869 /// Delete this group from its scene. 1864 /// Delete this group from its scene.
1870 /// </summary> 1865 /// </summary>
1871 /// 1866 /// <remarks>
1872 /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood 1867 /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood
1873 /// up and all avatars receive notification of its removal. Removal of the scene object from database backup 1868 /// up and all avatars receive notification of its removal. Removal of the scene object from database backup
1874 /// must be handled by the caller. 1869 /// must be handled by the caller.
1875 /// 1870 /// </remarks>
1876 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1871 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1877 public void DeleteGroupFromScene(bool silent) 1872 public void DeleteGroupFromScene(bool silent)
1878 { 1873 {
@@ -1901,7 +1896,7 @@ namespace OpenSim.Region.Framework.Scenes
1901 if (!IsAttachment 1896 if (!IsAttachment
1902 || AttachedAvatar == avatar.ControllingClient.AgentId 1897 || AttachedAvatar == avatar.ControllingClient.AgentId
1903 || !HasPrivateAttachmentPoint) 1898 || !HasPrivateAttachmentPoint)
1904 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); 1899 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
1905 } 1900 }
1906 } 1901 }
1907 }); 1902 });
@@ -2109,6 +2104,7 @@ namespace OpenSim.Region.Framework.Scenes
2109 2104
2110 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) 2105 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2111 { 2106 {
2107 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2112 RootPart.Shape.State = 0; 2108 RootPart.Shape.State = 0;
2113 ScheduleGroupForFullUpdate(); 2109 ScheduleGroupForFullUpdate();
2114 } 2110 }
@@ -2210,7 +2206,7 @@ namespace OpenSim.Region.Framework.Scenes
2210 if (!userExposed) 2206 if (!userExposed)
2211 dupe.IsAttachment = true; 2207 dupe.IsAttachment = true;
2212 2208
2213 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 2209 dupe.m_sittingAvatars = new List<UUID>();
2214 2210
2215 if (!userExposed) 2211 if (!userExposed)
2216 { 2212 {
@@ -3813,20 +3809,20 @@ namespace OpenSim.Region.Framework.Scenes
3813 /// <summary> 3809 /// <summary>
3814 /// Update just the root prim position in a linkset 3810 /// Update just the root prim position in a linkset
3815 /// </summary> 3811 /// </summary>
3816 /// <param name="pos"></param> 3812 /// <param name="newPos"></param>
3817 public void UpdateRootPosition(Vector3 pos) 3813 public void UpdateRootPosition(Vector3 newPos)
3818 { 3814 {
3819 // needs to be called with phys building true 3815 // needs to be called with phys building true
3820 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3816 Vector3 oldPos;
3821 Vector3 oldPos = 3817
3822 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3818 if (IsAttachment)
3823 AbsolutePosition.Y + m_rootPart.OffsetPosition.Y, 3819 oldPos = m_rootPart.AttachedPos + m_rootPart.OffsetPosition; // OffsetPosition should always be 0 in an attachments's root prim
3824 AbsolutePosition.Z + m_rootPart.OffsetPosition.Z); 3820 else
3821 oldPos = AbsolutePosition + m_rootPart.OffsetPosition;
3822
3825 Vector3 diff = oldPos - newPos; 3823 Vector3 diff = oldPos - newPos;
3826 Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
3827 Quaternion partRotation = m_rootPart.RotationOffset; 3824 Quaternion partRotation = m_rootPart.RotationOffset;
3828 axDiff *= Quaternion.Inverse(partRotation); 3825 diff *= Quaternion.Inverse(partRotation);
3829 diff = axDiff;
3830 3826
3831 SceneObjectPart[] parts = m_parts.GetArray(); 3827 SceneObjectPart[] parts = m_parts.GetArray();
3832 for (int i = 0; i < parts.Length; i++) 3828 for (int i = 0; i < parts.Length; i++)
@@ -3837,6 +3833,9 @@ namespace OpenSim.Region.Framework.Scenes
3837 } 3833 }
3838 3834
3839 AbsolutePosition = newPos; 3835 AbsolutePosition = newPos;
3836
3837 if (IsAttachment)
3838 m_rootPart.AttachedPos = newPos;
3840 3839
3841 HasGroupChanged = true; 3840 HasGroupChanged = true;
3842 if (m_rootPart.Undoing) 3841 if (m_rootPart.Undoing)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 261e958..ce9baaa 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -231,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes
231 231
232 public double SoundRadius; 232 public double SoundRadius;
233 233
234 /// <summary>
235 /// Should sounds played from this prim be queued?
236 /// </summary>
237 /// <remarks>
238 /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting.
239 /// </remarks>
240 public bool SoundQueueing { get; set; }
234 241
235 public uint TimeStampFull; 242 public uint TimeStampFull;
236 243
@@ -383,8 +390,6 @@ namespace OpenSim.Region.Framework.Scenes
383 390
384 private SOPVehicle m_vehicleParams = null; 391 private SOPVehicle m_vehicleParams = null;
385 392
386 private KeyframeMotion m_keyframeMotion = null;
387
388 public KeyframeMotion KeyframeMotion 393 public KeyframeMotion KeyframeMotion
389 { 394 {
390 get; set; 395 get; set;
@@ -506,7 +511,7 @@ namespace OpenSim.Region.Framework.Scenes
506 { 511 {
507 get 512 get
508 { 513 {
509 if (CreatorData != null && CreatorData != string.Empty) 514 if (!string.IsNullOrEmpty(CreatorData))
510 return CreatorID.ToString() + ';' + CreatorData; 515 return CreatorID.ToString() + ';' + CreatorData;
511 else 516 else
512 return CreatorID.ToString(); 517 return CreatorID.ToString();
@@ -536,7 +541,11 @@ namespace OpenSim.Region.Framework.Scenes
536 CreatorID = uuid; 541 CreatorID = uuid;
537 } 542 }
538 if (parts.Length >= 2) 543 if (parts.Length >= 2)
544 {
539 CreatorData = parts[1]; 545 CreatorData = parts[1];
546 if (!CreatorData.EndsWith("/"))
547 CreatorData += "/";
548 }
540 if (parts.Length >= 3) 549 if (parts.Length >= 3)
541 name = parts[2]; 550 name = parts[2];
542 551
@@ -815,7 +824,8 @@ namespace OpenSim.Region.Framework.Scenes
815 } 824 }
816 825
817 // Tell the physics engines that this prim changed. 826 // Tell the physics engines that this prim changed.
818 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 827 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
828 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
819 } 829 }
820 catch (Exception e) 830 catch (Exception e)
821 { 831 {
@@ -933,7 +943,7 @@ namespace OpenSim.Region.Framework.Scenes
933 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); 943 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString());
934 } 944 }
935 945
936 if (ParentGroup != null) 946 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
937 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 947 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
938 //} 948 //}
939 } 949 }
@@ -1218,23 +1228,14 @@ namespace OpenSim.Region.Framework.Scenes
1218 // the mappings more consistant. 1228 // the mappings more consistant.
1219 public Vector3 SitTargetPositionLL 1229 public Vector3 SitTargetPositionLL
1220 { 1230 {
1221 get { return new Vector3(m_sitTargetPosition.X, m_sitTargetPosition.Y,m_sitTargetPosition.Z); } 1231 get { return m_sitTargetPosition; }
1222 set { m_sitTargetPosition = value; } 1232 set { m_sitTargetPosition = value; }
1223 } 1233 }
1224 1234
1225 public Quaternion SitTargetOrientationLL 1235 public Quaternion SitTargetOrientationLL
1226 { 1236 {
1227 get 1237 get { return m_sitTargetOrientation; }
1228 { 1238 set { m_sitTargetOrientation = value; }
1229 return new Quaternion(
1230 m_sitTargetOrientation.X,
1231 m_sitTargetOrientation.Y,
1232 m_sitTargetOrientation.Z,
1233 m_sitTargetOrientation.W
1234 );
1235 }
1236
1237 set { m_sitTargetOrientation = new Quaternion(value.X, value.Y, value.Z, value.W); }
1238 } 1239 }
1239 1240
1240 public bool Stopped 1241 public bool Stopped
@@ -2959,6 +2960,26 @@ namespace OpenSim.Region.Framework.Scenes
2959 //ParentGroup.RootPart.m_groupPosition = newpos; 2960 //ParentGroup.RootPart.m_groupPosition = newpos;
2960 } 2961 }
2961 2962
2963 if (pa != null && ParentID != 0 && ParentGroup != null)
2964 {
2965 // Special case where a child object is requesting property updates.
2966 // This happens when linksets are modified to use flexible links rather than
2967 // the default links.
2968 // The simulator code presumes that child parts are only modified by scripts
2969 // so the logic for changing position/rotation/etc does not take into
2970 // account the physical object actually moving.
2971 // This code updates the offset position and rotation of the child and then
2972 // lets the update code push the update to the viewer.
2973 // Since physics engines do not normally generate this event for linkset children,
2974 // this code will not be active unless you have a specially configured
2975 // physics engine.
2976 Quaternion invRootRotation = Quaternion.Normalize(Quaternion.Inverse(ParentGroup.RootPart.RotationOffset));
2977 m_offsetPosition = pa.Position - m_groupPosition;
2978 RotationOffset = pa.Orientation * invRootRotation;
2979 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2980 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2981 }
2982
2962 ScheduleTerseUpdate(); 2983 ScheduleTerseUpdate();
2963 } 2984 }
2964 2985
@@ -3137,7 +3158,8 @@ namespace OpenSim.Region.Framework.Scenes
3137 return; 3158 return;
3138 3159
3139 // This was pulled from SceneViewer. Attachments always receive full updates. 3160 // This was pulled from SceneViewer. Attachments always receive full updates.
3140 // I could not verify if this is a requirement but this maintains existing behavior 3161 // This is needed because otherwise if only the root prim changes position, then
3162 // it looks as if the entire object has moved (including the other prims).
3141 if (ParentGroup.IsAttachment) 3163 if (ParentGroup.IsAttachment)
3142 { 3164 {
3143 ScheduleFullUpdate(); 3165 ScheduleFullUpdate();
@@ -4350,30 +4372,31 @@ namespace OpenSim.Region.Framework.Scenes
4350 } 4372 }
4351 } 4373 }
4352 4374
4353 public void UpdateGroupPosition(Vector3 pos) 4375 public void UpdateGroupPosition(Vector3 newPos)
4354 { 4376 {
4355 if ((pos.X != GroupPosition.X) || 4377 Vector3 oldPos = GroupPosition;
4356 (pos.Y != GroupPosition.Y) || 4378
4357 (pos.Z != GroupPosition.Z)) 4379 if ((newPos.X != oldPos.X) ||
4380 (newPos.Y != oldPos.Y) ||
4381 (newPos.Z != oldPos.Z))
4358 { 4382 {
4359 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4360 GroupPosition = newPos; 4383 GroupPosition = newPos;
4361 ScheduleTerseUpdate(); 4384 ScheduleTerseUpdate();
4362 } 4385 }
4363 } 4386 }
4364 4387
4365 /// <summary> 4388 /// <summary>
4366 /// 4389 /// Update this part's offset position.
4367 /// </summary> 4390 /// </summary>
4368 /// <param name="pos"></param> 4391 /// <param name="pos"></param>
4369 public void UpdateOffSet(Vector3 pos) 4392 public void UpdateOffSet(Vector3 newPos)
4370 { 4393 {
4371 if ((pos.X != OffsetPosition.X) || 4394 Vector3 oldPos = OffsetPosition;
4372 (pos.Y != OffsetPosition.Y) ||
4373 (pos.Z != OffsetPosition.Z))
4374 {
4375 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4376 4395
4396 if ((newPos.X != oldPos.X) ||
4397 (newPos.Y != oldPos.Y) ||
4398 (newPos.Z != oldPos.Z))
4399 {
4377 if (ParentGroup.RootPart.GetStatusSandbox()) 4400 if (ParentGroup.RootPart.GetStatusSandbox())
4378 { 4401 {
4379 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) 4402 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10)
@@ -4520,7 +4543,7 @@ namespace OpenSim.Region.Framework.Scenes
4520 // For now, we use the NINJA naming scheme for identifying joints. 4543 // For now, we use the NINJA naming scheme for identifying joints.
4521 // In the future, we can support other joint specification schemes such as a 4544 // In the future, we can support other joint specification schemes such as a
4522 // custom checkbox in the viewer GUI. 4545 // custom checkbox in the viewer GUI.
4523 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4546 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4524 { 4547 {
4525 return IsHingeJoint() || IsBallJoint(); 4548 return IsHingeJoint() || IsBallJoint();
4526 } 4549 }
@@ -4642,6 +4665,11 @@ namespace OpenSim.Region.Framework.Scenes
4642 } 4665 }
4643 } 4666 }
4644*/ 4667*/
4668 if (pa != null)
4669 {
4670 pa.SetMaterial(Material);
4671 DoPhysicsPropertyUpdate(UsePhysics, true);
4672 }
4645 } 4673 }
4646 else // it already has a physical representation 4674 else // it already has a physical representation
4647 { 4675 {
@@ -5014,6 +5042,14 @@ namespace OpenSim.Region.Framework.Scenes
5014 oldTex.DefaultTexture = fallbackOldFace; 5042 oldTex.DefaultTexture = fallbackOldFace;
5015 } 5043 }
5016 5044
5045 // Materials capable viewers can send a ObjectImage packet
5046 // when nothing in TE has changed. MaterialID should be updated
5047 // by the RenderMaterials CAP handler, so updating it here may cause a
5048 // race condtion. Therefore, if no non-materials TE fields have changed,
5049 // we should ignore any changes and not update Shape.TextureEntry
5050
5051 bool otherFieldsChanged = false;
5052
5017 for (int i = 0 ; i < GetNumberOfSides(); i++) 5053 for (int i = 0 ; i < GetNumberOfSides(); i++)
5018 { 5054 {
5019 5055
@@ -5040,18 +5076,36 @@ namespace OpenSim.Region.Framework.Scenes
5040 // Max change, skip the rest of testing 5076 // Max change, skip the rest of testing
5041 if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) 5077 if (changeFlags == (Changed.TEXTURE | Changed.COLOR))
5042 break; 5078 break;
5079
5080 if (!otherFieldsChanged)
5081 {
5082 if (oldFace.Bump != newFace.Bump) otherFieldsChanged = true;
5083 if (oldFace.Fullbright != newFace.Fullbright) otherFieldsChanged = true;
5084 if (oldFace.Glow != newFace.Glow) otherFieldsChanged = true;
5085 if (oldFace.MediaFlags != newFace.MediaFlags) otherFieldsChanged = true;
5086 if (oldFace.OffsetU != newFace.OffsetU) otherFieldsChanged = true;
5087 if (oldFace.OffsetV != newFace.OffsetV) otherFieldsChanged = true;
5088 if (oldFace.RepeatU != newFace.RepeatU) otherFieldsChanged = true;
5089 if (oldFace.RepeatV != newFace.RepeatV) otherFieldsChanged = true;
5090 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true;
5091 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true;
5092 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true;
5093 }
5043 } 5094 }
5044 5095
5045 m_shape.TextureEntry = newTex.GetBytes(); 5096 if (changeFlags != 0 || otherFieldsChanged)
5046 if (changeFlags != 0) 5097 {
5047 TriggerScriptChangedEvent(changeFlags); 5098 m_shape.TextureEntry = newTex.GetBytes();
5048 UpdateFlag = UpdateRequired.FULL; 5099 if (changeFlags != 0)
5049 ParentGroup.HasGroupChanged = true; 5100 TriggerScriptChangedEvent(changeFlags);
5101 UpdateFlag = UpdateRequired.FULL;
5102 ParentGroup.HasGroupChanged = true;
5050 5103
5051 //This is madness.. 5104 //This is madness..
5052 //ParentGroup.ScheduleGroupForFullUpdate(); 5105 //ParentGroup.ScheduleGroupForFullUpdate();
5053 //This is sparta 5106 //This is sparta
5054 ScheduleFullUpdate(); 5107 ScheduleFullUpdate();
5108 }
5055 } 5109 }
5056 5110
5057 5111
@@ -5239,6 +5293,64 @@ namespace OpenSim.Region.Framework.Scenes
5239 { 5293 {
5240 ParentGroup.AddScriptLPS(count); 5294 ParentGroup.AddScriptLPS(count);
5241 } 5295 }
5296
5297 /// <summary>
5298 /// Sets a prim's owner and permissions when it's rezzed.
5299 /// </summary>
5300 /// <param name="item">The inventory item from which the item was rezzed</param>
5301 /// <param name="userInventory">True: the item is being rezzed from the user's inventory. False: from a prim's inventory.</param>
5302 /// <param name="scene">The scene the prim is being rezzed into</param>
5303 public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene)
5304 {
5305 if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0))
5306 {
5307 if (scene.Permissions.PropagatePermissions())
5308 {
5309 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
5310 {
5311 // Apply the item's permissions to the object
5312 //LogPermissions("Before applying item permissions");
5313 if (userInventory)
5314 {
5315 EveryoneMask = item.EveryOnePermissions;
5316 NextOwnerMask = item.NextPermissions;
5317 }
5318 else
5319 {
5320 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
5321 EveryoneMask = item.EveryOnePermissions;
5322 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
5323 NextOwnerMask = item.NextPermissions;
5324 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
5325 GroupMask = item.GroupPermissions;
5326 }
5327 //LogPermissions("After applying item permissions");
5328 }
5329 }
5330
5331 GroupMask = 0; // DO NOT propagate here
5332 }
5333
5334 if (OwnerID != item.Owner)
5335 {
5336 //LogPermissions("Before ApplyNextOwnerPermissions");
5337 ApplyNextOwnerPermissions();
5338 //LogPermissions("After ApplyNextOwnerPermissions");
5339
5340 LastOwnerID = OwnerID;
5341 OwnerID = item.Owner;
5342 Inventory.ChangeInventoryOwner(item.Owner);
5343 }
5344 }
5345
5346 /// <summary>
5347 /// Logs the prim's permissions. Useful when debugging permission problems.
5348 /// </summary>
5349 /// <param name="message"></param>
5350 private void LogPermissions(String message)
5351 {
5352 PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask);
5353 }
5242 5354
5243 public void ApplyNextOwnerPermissions() 5355 public void ApplyNextOwnerPermissions()
5244 { 5356 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index d04d87b..8893cc0 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -696,7 +696,8 @@ namespace OpenSim.Region.Framework.Scenes
696 /// </param> 696 /// </param>
697 public void StopScriptInstance(TaskInventoryItem item) 697 public void StopScriptInstance(TaskInventoryItem item)
698 { 698 {
699 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID); 699 if (m_part.ParentGroup.Scene != null)
700 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID);
700 701
701 // At the moment, even stopped scripts are counted as active, which is probably wrong. 702 // At the moment, even stopped scripts are counted as active, which is probably wrong.
702// m_part.ParentGroup.AddActiveScriptCount(-1); 703// m_part.ParentGroup.AddActiveScriptCount(-1);
@@ -880,8 +881,8 @@ namespace OpenSim.Region.Framework.Scenes
880 881
881 return items; 882 return items;
882 } 883 }
883 884
884 public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item) 885 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist)
885 { 886 {
886 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 887 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
887 888
@@ -890,70 +891,58 @@ namespace OpenSim.Region.Framework.Scenes
890 m_log.WarnFormat( 891 m_log.WarnFormat(
891 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", 892 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
892 item.AssetID, item.Name, m_part.Name); 893 item.AssetID, item.Name, m_part.Name);
893 return null; 894 objlist = null;
895 veclist = null;
896 return false;
894 } 897 }
895 898
896 string xmlData = Utils.BytesToString(rezAsset.Data); 899 Vector3 bbox;
897 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 900 float offsetHeight;
898 901
899 group.RootPart.AttachPoint = group.RootPart.Shape.State; 902 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
900 group.RootPart.AttachOffset = group.AbsolutePosition;
901 group.RootPart.AttachRotation = group.GroupRotation;
902 903
903 group.ResetIDs(); 904 for (int i = 0; i < objlist.Count; i++)
904 905 {
905 SceneObjectPart rootPart = group.GetPart(group.UUID); 906 SceneObjectGroup group = objlist[i];
906 907
907 // Since renaming the item in the inventory does not affect the name stored 908 group.RootPart.AttachPoint = group.RootPart.Shape.State;
908 // in the serialization, transfer the correct name from the inventory to the 909 group.RootPart.AttachOffset = group.AbsolutePosition;
909 // object itself before we rez. 910 group.RootPart.AttachRotation = group.GroupRotation;
910 rootPart.Name = item.Name;
911 rootPart.Description = item.Description;
912 911
913 SceneObjectPart[] partList = group.Parts; 912 group.ResetIDs();
914 913
915 group.SetGroup(m_part.GroupID, null); 914 SceneObjectPart rootPart = group.GetPart(group.UUID);
916 915
917 // TODO: Remove magic number badness 916 // Since renaming the item in the inventory does not affect the name stored
918 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number 917 // in the serialization, transfer the correct name from the inventory to the
919 { 918 // object itself before we rez.
920 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) 919 // Only do these for the first object if we are rezzing a coalescence.
920 if (i == 0)
921 { 921 {
922 foreach (SceneObjectPart part in partList) 922 rootPart.Name = item.Name;
923 { 923 rootPart.Description = item.Description;
924 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
925 part.EveryoneMask = item.EveryonePermissions;
926 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
927 part.NextOwnerMask = item.NextPermissions;
928 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
929 part.GroupMask = item.GroupPermissions;
930 }
931
932 group.ApplyNextOwnerPermissions();
933 } 924 }
934 }
935 925
936 foreach (SceneObjectPart part in partList) 926 group.SetGroup(m_part.GroupID, null);
937 { 927
938 // TODO: Remove magic number badness 928 foreach (SceneObjectPart part in group.Parts)
939 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
940 { 929 {
941 part.LastOwnerID = part.OwnerID; 930 // Convert between InventoryItem classes. You can never have too many similar but slightly different classes :)
942 part.OwnerID = item.OwnerID; 931 InventoryItemBase dest = new InventoryItemBase(item.ItemID, item.OwnerID);
943 part.Inventory.ChangeInventoryOwner(item.OwnerID); 932 dest.BasePermissions = item.BasePermissions;
933 dest.CurrentPermissions = item.CurrentPermissions;
934 dest.EveryOnePermissions = item.EveryonePermissions;
935 dest.GroupPermissions = item.GroupPermissions;
936 dest.NextPermissions = item.NextPermissions;
937 dest.Flags = item.Flags;
938
939 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene);
944 } 940 }
945 941
946 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 942 rootPart.TrimPermissions();
947 part.EveryoneMask = item.EveryonePermissions;
948 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
949 part.NextOwnerMask = item.NextPermissions;
950 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
951 part.GroupMask = item.GroupPermissions;
952 } 943 }
953 944
954 rootPart.TrimPermissions(); 945 return true;
955
956 return group;
957 } 946 }
958 947
959 /// <summary> 948 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 7004d23..f57d4fe 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -29,7 +29,9 @@ using System;
29using System.Xml; 29using System.Xml;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using System.Timers; 33using System.Timers;
34using Timer = System.Timers.Timer;
33using OpenMetaverse; 35using OpenMetaverse;
34using log4net; 36using log4net;
35using Nini.Config; 37using Nini.Config;
@@ -73,21 +75,50 @@ namespace OpenSim.Region.Framework.Scenes
73 75
74 public class ScenePresence : EntityBase, IScenePresence 76 public class ScenePresence : EntityBase, IScenePresence
75 { 77 {
78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
79
76// ~ScenePresence() 80// ~ScenePresence()
77// { 81// {
78// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); 82// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
79// } 83// }
80 84
81 private void TriggerScenePresenceUpdated() 85 public void TriggerScenePresenceUpdated()
82 { 86 {
83 if (m_scene != null) 87 if (m_scene != null)
84 m_scene.EventManager.TriggerScenePresenceUpdated(this); 88 m_scene.EventManager.TriggerScenePresenceUpdated(this);
85 } 89 }
86 90
87 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
88
89 public PresenceType PresenceType { get; private set; } 91 public PresenceType PresenceType { get; private set; }
90 92
93 private ScenePresenceStateMachine m_stateMachine;
94
95 /// <summary>
96 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
97 /// for more details.
98 /// </summary>
99 public ScenePresenceState LifecycleState
100 {
101 get
102 {
103 return m_stateMachine.GetState();
104 }
105
106 set
107 {
108 m_stateMachine.SetState(value);
109 }
110 }
111
112 /// <summary>
113 /// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and
114 /// the viewer fires these in quick succession.
115 /// </summary>
116 /// <remarks>
117 /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement
118 /// regulation done there.
119 /// </remarks>
120 private object m_completeMovementLock = new object();
121
91// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 122// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
92 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 123 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
93 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); 124 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
@@ -142,6 +173,8 @@ namespace OpenSim.Region.Framework.Scenes
142 private Vector3 m_lastVelocity; 173 private Vector3 m_lastVelocity;
143 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); 174 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
144 175
176 private bool m_followCamAuto = false;
177
145 178
146 private Vector3? m_forceToApply; 179 private Vector3? m_forceToApply;
147 private int m_userFlags; 180 private int m_userFlags;
@@ -200,7 +233,7 @@ namespace OpenSim.Region.Framework.Scenes
200 private float m_sitAvatarHeight = 2.0f; 233 private float m_sitAvatarHeight = 2.0f;
201 234
202 private Vector3 m_lastChildAgentUpdatePosition; 235 private Vector3 m_lastChildAgentUpdatePosition;
203 private Vector3 m_lastChildAgentUpdateCamPosition; 236// private Vector3 m_lastChildAgentUpdateCamPosition;
204 237
205 private const int LAND_VELOCITYMAG_MAX = 12; 238 private const int LAND_VELOCITYMAG_MAX = 12;
206 239
@@ -290,9 +323,37 @@ namespace OpenSim.Region.Framework.Scenes
290 /// </summary> 323 /// </summary>
291 private Vector3 posLastSignificantMove; 324 private Vector3 posLastSignificantMove;
292 325
293 // For teleports and crossings callbacks 326 #region For teleports and crossings callbacks
294 string m_callbackURI; 327
295 UUID m_originRegionID; 328 /// <summary>
329 /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
330 /// </summary>
331 private string m_callbackURI;
332
333 /// <summary>
334 /// Records the region from which this presence originated, if not from login.
335 /// </summary>
336 /// <remarks>
337 /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered
338 /// CompleteMovement and made the previous child agent a root agent.
339 /// </remarks>
340 private UUID m_originRegionID;
341
342 /// <summary>
343 /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing
344 /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as
345 /// it is a value type.
346 /// </summary>
347 private object m_originRegionIDAccessLock = new object();
348
349 /// <summary>
350 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
351 /// teleport is reusing the connection.
352 /// </summary>
353 /// <remarks>May be refactored or move somewhere else soon.</remarks>
354 public bool DoNotCloseAfterTeleport { get; set; }
355
356 #endregion
296 357
297 /// <value> 358 /// <value>
298 /// Script engines present in the scene 359 /// Script engines present in the scene
@@ -309,15 +370,12 @@ namespace OpenSim.Region.Framework.Scenes
309 /// <summary> 370 /// <summary>
310 /// Record user movement inputs. 371 /// Record user movement inputs.
311 /// </summary> 372 /// </summary>
312 public byte MovementFlag { get; private set; } 373 public uint MovementFlag { get; private set; }
313 374
314 private bool m_updateflag; 375 /// <summary>
315 376 /// Is the agent stop control flag currently active?
316 public bool Updated 377 /// </summary>
317 { 378 public bool AgentControlStopActive { get; private set; }
318 set { m_updateflag = value; }
319 get { return m_updateflag; }
320 }
321 379
322 private bool m_invulnerable = true; 380 private bool m_invulnerable = true;
323 381
@@ -462,6 +520,7 @@ namespace OpenSim.Region.Framework.Scenes
462 } 520 }
463 else 521 else
464 { 522 {
523// m_log.DebugFormat("[SCENE PRESENCE]: Fetching abs pos where PhysicsActor == null and parent part {0} for {1}", Name, Scene.Name);
465 // Obtain the correct position of a seated avatar. 524 // Obtain the correct position of a seated avatar.
466 // In addition to providing the correct position while 525 // In addition to providing the correct position while
467 // the avatar is seated, this value will also 526 // the avatar is seated, this value will also
@@ -485,7 +544,7 @@ namespace OpenSim.Region.Framework.Scenes
485 } 544 }
486 set 545 set
487 { 546 {
488// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value); 547// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name);
489// Util.PrintCallStack(); 548// Util.PrintCallStack();
490 549
491 if (PhysicsActor != null) 550 if (PhysicsActor != null)
@@ -502,10 +561,7 @@ namespace OpenSim.Region.Framework.Scenes
502 561
503 // Don't update while sitting. The PhysicsActor above is null whilst sitting. 562 // Don't update while sitting. The PhysicsActor above is null whilst sitting.
504 if (ParentID == 0) 563 if (ParentID == 0)
505 {
506 m_pos = value; 564 m_pos = value;
507// ParentPosition = Vector3.Zero;
508 }
509 565
510 //m_log.DebugFormat( 566 //m_log.DebugFormat(
511 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", 567 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
@@ -768,6 +824,14 @@ namespace OpenSim.Region.Framework.Scenes
768 set { m_speedModifier = value; } 824 set { m_speedModifier = value; }
769 } 825 }
770 826
827 /// <summary>
828 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
829 /// </summary>
830 /// <remarks>
831 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
832 /// </remarks>
833 private float AgentControlStopSlowWhilstMoving = 0.5f;
834
771 private bool m_forceFly; 835 private bool m_forceFly;
772 836
773 public bool ForceFly 837 public bool ForceFly
@@ -795,7 +859,7 @@ namespace OpenSim.Region.Framework.Scenes
795 859
796 public ScenePresence( 860 public ScenePresence(
797 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 861 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
798 { 862 {
799 AttachmentsSyncLock = new Object(); 863 AttachmentsSyncLock = new Object();
800 AllowMovement = true; 864 AllowMovement = true;
801 IsChildAgent = true; 865 IsChildAgent = true;
@@ -841,6 +905,8 @@ namespace OpenSim.Region.Framework.Scenes
841 SetDirectionVectors(); 905 SetDirectionVectors();
842 906
843 Appearance = appearance; 907 Appearance = appearance;
908
909 m_stateMachine = new ScenePresenceStateMachine(this);
844 } 910 }
845 911
846 private void RegionHeartbeatEnd(Scene scene) 912 private void RegionHeartbeatEnd(Scene scene)
@@ -874,6 +940,7 @@ namespace OpenSim.Region.Framework.Scenes
874 { 940 {
875 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 941 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
876 ControllingClient.OnAgentUpdate += HandleAgentUpdate; 942 ControllingClient.OnAgentUpdate += HandleAgentUpdate;
943 ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate;
877 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; 944 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit;
878 ControllingClient.OnAgentSit += HandleAgentSit; 945 ControllingClient.OnAgentSit += HandleAgentSit;
879 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 946 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
@@ -927,6 +994,7 @@ namespace OpenSim.Region.Framework.Scenes
927 /// <summary> 994 /// <summary>
928 /// Turns a child agent into a root agent. 995 /// Turns a child agent into a root agent.
929 /// </summary> 996 /// </summary>
997 /// <remarks>
930 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the 998 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the
931 /// avatar is actual in the sim. They can perform all actions. 999 /// avatar is actual in the sim. They can perform all actions.
932 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, 1000 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim,
@@ -934,48 +1002,56 @@ namespace OpenSim.Region.Framework.Scenes
934 /// 1002 ///
935 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1003 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
936 /// delays that crossing. 1004 /// delays that crossing.
937 /// </summary> 1005 /// </remarks>
938 public void MakeRootAgent(Vector3 pos, bool isFlying) 1006 private bool MakeRootAgent(Vector3 pos, bool isFlying)
939 { 1007 {
940 m_log.DebugFormat( 1008 lock (m_completeMovementLock)
941 "[SCENE]: Upgrading child to root agent for {0} in {1}",
942 Name, m_scene.RegionInfo.RegionName);
943
944 if (ParentUUID != UUID.Zero)
945 { 1009 {
946 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); 1010 if (!IsChildAgent)
947 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); 1011 return false;
948 if (part == null) 1012
1013 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1014
1015 // m_log.InfoFormat(
1016 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1017 // Name, m_scene.RegionInfo.RegionName);
1018
1019 if (ParentUUID != UUID.Zero)
949 { 1020 {
950 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1021 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1022 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1023 if (part == null)
1024 {
1025 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1026 }
1027 else
1028 {
1029 part.ParentGroup.AddAvatar(UUID);
1030 if (part.SitTargetPosition != Vector3.Zero)
1031 part.SitTargetAvatar = UUID;
1032 // ParentPosition = part.GetWorldPosition();
1033 ParentID = part.LocalId;
1034 ParentPart = part;
1035 m_pos = PrevSitOffset;
1036 // pos = ParentPosition;
1037 pos = part.GetWorldPosition();
1038 }
1039 ParentUUID = UUID.Zero;
1040
1041 // Animator.TrySetMovementAnimation("SIT");
951 } 1042 }
952 else 1043 else
953 { 1044 {
954 part.ParentGroup.AddAvatar(UUID); 1045 IsLoggingIn = false;
955 if (part.SitTargetPosition != Vector3.Zero)
956 part.SitTargetAvatar = UUID;
957// ParentPosition = part.GetWorldPosition();
958 ParentID = part.LocalId;
959 ParentPart = part;
960 m_pos = PrevSitOffset;
961// pos = ParentPosition;
962 pos = part.GetWorldPosition();
963 } 1046 }
964 ParentUUID = UUID.Zero;
965 1047
966 IsChildAgent = false; 1048 IsChildAgent = false;
967
968// Animator.TrySetMovementAnimation("SIT");
969 } 1049 }
970 else
971 {
972 IsChildAgent = false;
973 IsLoggingIn = false;
974 }
975
976 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
977 1050
978 IsChildAgent = false; 1051 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1052 // set and prevent the close of the connection on a subsequent re-teleport.
1053 // Should not be needed if we are not trying to tell this region to close
1054// DoNotCloseAfterTeleport = false;
979 1055
980 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1056 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
981 if (gm != null) 1057 if (gm != null)
@@ -1116,22 +1192,36 @@ namespace OpenSim.Region.Framework.Scenes
1116 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently 1192 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1117 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are 1193 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1118 // not transporting the required data. 1194 // not transporting the required data.
1119 lock (m_attachments) 1195 //
1196 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1197 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1198 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1199 // not transporting the required data.
1200 //
1201 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1202 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1203 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
1204 //
1205 // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
1206 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1207 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1208 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1209 //
1210 // One cannot simply iterate over attachments in a fire and forget thread because this would no longer
1211 // be locked, allowing race conditions if other code changes the attachments list.
1212 List<SceneObjectGroup> attachments = GetAttachments();
1213
1214 if (attachments.Count > 0)
1120 { 1215 {
1121 if (HasAttachments()) 1216 m_log.DebugFormat(
1122 { 1217 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1123 m_log.DebugFormat(
1124 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1125 1218
1126 // Resume scripts 1219 // Resume scripts
1127 Util.FireAndForget(delegate(object x) { 1220 foreach (SceneObjectGroup sog in attachments)
1128 foreach (SceneObjectGroup sog in m_attachments) 1221 {
1129 { 1222 sog.ScheduleGroupForFullUpdate();
1130 sog.ScheduleGroupForFullUpdate(); 1223 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1131 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 1224 sog.ResumeScripts();
1132 sog.ResumeScripts();
1133 }
1134 });
1135 } 1225 }
1136 } 1226 }
1137 } 1227 }
@@ -1153,7 +1243,7 @@ namespace OpenSim.Region.Framework.Scenes
1153 1243
1154 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1244 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1155 1245
1156 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; 1246 return true;
1157 } 1247 }
1158 1248
1159 public int GetStateSource() 1249 public int GetStateSource()
@@ -1306,7 +1396,26 @@ namespace OpenSim.Region.Framework.Scenes
1306 1396
1307 public void StopFlying() 1397 public void StopFlying()
1308 { 1398 {
1309 ControllingClient.StopFlying(this); 1399 Vector3 pos = AbsolutePosition;
1400 if (Appearance.AvatarHeight != 127.0f)
1401 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1402 else
1403 pos += new Vector3(0f, 0f, (1.56f / 6f));
1404
1405 AbsolutePosition = pos;
1406
1407 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
1408 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
1409 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
1410 // certain amount.. because the LLClient wouldn't land in that situation anyway.
1411
1412 // why are we still testing for this really old height value default???
1413 if (Appearance.AvatarHeight != 127.0f)
1414 CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f);
1415 else
1416 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1417
1418 ControllingClient.SendAgentTerseUpdate(this);
1310 } 1419 }
1311 1420
1312 /// <summary> 1421 /// <summary>
@@ -1480,6 +1589,37 @@ namespace OpenSim.Region.Framework.Scenes
1480 1589
1481 } 1590 }
1482 1591
1592 private bool WaitForUpdateAgent(IClientAPI client)
1593 {
1594 // Before the source region executes UpdateAgent
1595 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1596 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1597 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1598 int count = 50;
1599 UUID originID;
1600
1601 lock (m_originRegionIDAccessLock)
1602 originID = m_originRegionID;
1603
1604 while (originID.Equals(UUID.Zero) && count-- > 0)
1605 {
1606 lock (m_originRegionIDAccessLock)
1607 originID = m_originRegionID;
1608
1609 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1610 Thread.Sleep(200);
1611 }
1612
1613 if (originID.Equals(UUID.Zero))
1614 {
1615 // Movement into region will fail
1616 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
1617 return false;
1618 }
1619
1620 return true;
1621 }
1622
1483 /// <summary> 1623 /// <summary>
1484 /// Complete Avatar's movement into the region. 1624 /// Complete Avatar's movement into the region.
1485 /// </summary> 1625 /// </summary>
@@ -1493,9 +1633,18 @@ namespace OpenSim.Region.Framework.Scenes
1493 { 1633 {
1494// DateTime startTime = DateTime.Now; 1634// DateTime startTime = DateTime.Now;
1495 1635
1496 m_log.DebugFormat( 1636 m_log.InfoFormat(
1497 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1637 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1498 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); 1638 client.Name, Scene.Name, AbsolutePosition);
1639
1640 // Make sure it's not a login agent. We don't want to wait for updates during login
1641 if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
1642 {
1643 // Let's wait until UpdateAgent (called by departing region) is done
1644 if (!WaitForUpdateAgent(client))
1645 // The sending region never sent the UpdateAgent data, we have to refuse
1646 return;
1647 }
1499 1648
1500 Vector3 look = Velocity; 1649 Vector3 look = Velocity;
1501 1650
@@ -1517,12 +1666,25 @@ namespace OpenSim.Region.Framework.Scenes
1517 } 1666 }
1518 1667
1519 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1668 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1520 MakeRootAgent(AbsolutePosition, flying); 1669 if (!MakeRootAgent(AbsolutePosition, flying))
1670 {
1671 m_log.DebugFormat(
1672 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1673 Name, Scene.Name);
1674
1675 return;
1676 }
1677
1678 // Tell the client that we're totally ready
1521 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); 1679 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1522 1680
1681 // Remember in HandleUseCircuitCode, we delayed this to here
1682 if (m_teleportFlags > 0)
1683 SendInitialDataToMe();
1684
1523// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); 1685// m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1524 1686
1525 if ((m_callbackURI != null) && !m_callbackURI.Equals("")) 1687 if (!string.IsNullOrEmpty(m_callbackURI))
1526 { 1688 {
1527 // We cannot sleep here since this would hold up the inbound packet processing thread, as 1689 // We cannot sleep here since this would hold up the inbound packet processing thread, as
1528 // CompleteMovement() is executed synchronously. However, it might be better to delay the release 1690 // CompleteMovement() is executed synchronously. However, it might be better to delay the release
@@ -1535,7 +1697,12 @@ namespace OpenSim.Region.Framework.Scenes
1535 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 1697 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1536 client.Name, client.AgentId, m_callbackURI); 1698 client.Name, client.AgentId, m_callbackURI);
1537 1699
1538 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1700 UUID originID;
1701
1702 lock (m_originRegionIDAccessLock)
1703 originID = m_originRegionID;
1704
1705 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1539 m_callbackURI = null; 1706 m_callbackURI = null;
1540 } 1707 }
1541// else 1708// else
@@ -1550,7 +1717,6 @@ namespace OpenSim.Region.Framework.Scenes
1550 // Create child agents in neighbouring regions 1717 // Create child agents in neighbouring regions
1551 if (openChildAgents && !IsChildAgent) 1718 if (openChildAgents && !IsChildAgent)
1552 { 1719 {
1553
1554 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1720 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
1555 if (m_agentTransfer != null) 1721 if (m_agentTransfer != null)
1556 m_agentTransfer.EnableChildAgents(this); 1722 m_agentTransfer.EnableChildAgents(this);
@@ -1573,6 +1739,7 @@ namespace OpenSim.Region.Framework.Scenes
1573// m_log.DebugFormat( 1739// m_log.DebugFormat(
1574// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 1740// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1575// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); 1741// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
1742
1576 } 1743 }
1577 1744
1578 /// <summary> 1745 /// <summary>
@@ -1653,9 +1820,9 @@ namespace OpenSim.Region.Framework.Scenes
1653 /// </summary> 1820 /// </summary>
1654 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 1821 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1655 { 1822 {
1656// m_log.DebugFormat( 1823 //m_log.DebugFormat(
1657// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", 1824 // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
1658// Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); 1825 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
1659 1826
1660 if (IsChildAgent) 1827 if (IsChildAgent)
1661 { 1828 {
@@ -1663,10 +1830,6 @@ namespace OpenSim.Region.Framework.Scenes
1663 return; 1830 return;
1664 } 1831 }
1665 1832
1666 ++m_movementUpdateCount;
1667 if (m_movementUpdateCount < 1)
1668 m_movementUpdateCount = 1;
1669
1670 #region Sanity Checking 1833 #region Sanity Checking
1671 1834
1672 // This is irritating. Really. 1835 // This is irritating. Really.
@@ -1697,21 +1860,6 @@ namespace OpenSim.Region.Framework.Scenes
1697 1860
1698 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; 1861 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
1699 1862
1700 // Camera location in world. We'll need to raytrace
1701 // from this location from time to time.
1702 CameraPosition = agentData.CameraCenter;
1703 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
1704 {
1705 ReprioritizeUpdates();
1706 m_lastCameraPosition = CameraPosition;
1707 }
1708
1709 // Use these three vectors to figure out what the agent is looking at
1710 // Convert it to a Matrix and/or Quaternion
1711 CameraAtAxis = agentData.CameraAtAxis;
1712 CameraLeftAxis = agentData.CameraLeftAxis;
1713 CameraUpAxis = agentData.CameraUpAxis;
1714
1715 // The Agent's Draw distance setting 1863 // The Agent's Draw distance setting
1716 // When we get to the point of re-computing neighbors everytime this 1864 // When we get to the point of re-computing neighbors everytime this
1717 // changes, then start using the agent's drawdistance rather than the 1865 // changes, then start using the agent's drawdistance rather than the
@@ -1783,9 +1931,16 @@ namespace OpenSim.Region.Framework.Scenes
1783 // Here's where you get them. 1931 // Here's where you get them.
1784 m_AgentControlFlags = flags; 1932 m_AgentControlFlags = flags;
1785 m_headrotation = agentData.HeadRotation; 1933 m_headrotation = agentData.HeadRotation;
1934 byte oldState = State;
1786 State = agentData.State; 1935 State = agentData.State;
1787 1936
1937 // We need to send this back to the client in order to stop the edit beams
1938 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
1939 ControllingClient.SendAgentTerseUpdate(this);
1940
1788 PhysicsActor actor = PhysicsActor; 1941 PhysicsActor actor = PhysicsActor;
1942
1943 // This will be the case if the agent is sitting on the groudn or on an object.
1789 if (actor == null) 1944 if (actor == null)
1790 { 1945 {
1791 SendControlsToScripts(flagsForScripts); 1946 SendControlsToScripts(flagsForScripts);
@@ -1794,12 +1949,13 @@ namespace OpenSim.Region.Framework.Scenes
1794 1949
1795 if (AllowMovement && !SitGround) 1950 if (AllowMovement && !SitGround)
1796 { 1951 {
1797 Quaternion bodyRotation = agentData.BodyRotation; 1952// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
1953
1798 bool update_rotation = false; 1954 bool update_rotation = false;
1799 1955
1800 if (bodyRotation != Rotation) 1956 if (agentData.BodyRotation != Rotation)
1801 { 1957 {
1802 Rotation = bodyRotation; 1958 Rotation = agentData.BodyRotation;
1803 update_rotation = true; 1959 update_rotation = true;
1804 } 1960 }
1805 1961
@@ -1845,10 +2001,7 @@ namespace OpenSim.Region.Framework.Scenes
1845 else 2001 else
1846 dirVectors = Dir_Vectors; 2002 dirVectors = Dir_Vectors;
1847 2003
1848 // The fact that MovementFlag is a byte needs to be fixed
1849 // it really should be a uint
1850 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 2004 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
1851 uint nudgehack = 250;
1852 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 2005 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1853 { 2006 {
1854 if (((uint)flags & (uint)DCF) != 0) 2007 if (((uint)flags & (uint)DCF) != 0)
@@ -1865,29 +2018,19 @@ namespace OpenSim.Region.Framework.Scenes
1865 // Why did I get this? 2018 // Why did I get this?
1866 } 2019 }
1867 2020
1868 if ((MovementFlag & (byte)(uint)DCF) == 0) 2021 if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive)
1869 { 2022 {
1870 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1871 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1872 {
1873 MovementFlag |= (byte)nudgehack;
1874 }
1875
1876 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 2023 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
1877 MovementFlag += (byte)(uint)DCF; 2024 MovementFlag += (uint)DCF;
1878 update_movementflag = true; 2025 update_movementflag = true;
1879 } 2026 }
1880 } 2027 }
1881 else 2028 else
1882 { 2029 {
1883 if ((MovementFlag & (byte)(uint)DCF) != 0 || 2030 if ((MovementFlag & (uint)DCF) != 0)
1884 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1885 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1886 && ((MovementFlag & (byte)nudgehack) == nudgehack))
1887 ) // This or is for Nudge forward
1888 { 2031 {
1889 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2032 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
1890 MovementFlag -= ((byte)(uint)DCF); 2033 MovementFlag -= (uint)DCF;
1891 update_movementflag = true; 2034 update_movementflag = true;
1892 2035
1893 /* 2036 /*
@@ -1907,6 +2050,13 @@ namespace OpenSim.Region.Framework.Scenes
1907 i++; 2050 i++;
1908 } 2051 }
1909 2052
2053 // Detect AGENT_CONTROL_STOP state changes
2054 if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0))
2055 {
2056 AgentControlStopActive = !AgentControlStopActive;
2057 update_movementflag = true;
2058 }
2059
1910 if (MovingToTarget) 2060 if (MovingToTarget)
1911 { 2061 {
1912 // If the user has pressed a key then we want to cancel any move to target. 2062 // If the user has pressed a key then we want to cancel any move to target.
@@ -1932,53 +2082,79 @@ namespace OpenSim.Region.Framework.Scenes
1932 // Only do this if we're flying 2082 // Only do this if we're flying
1933 if (Flying && !ForceFly) 2083 if (Flying && !ForceFly)
1934 { 2084 {
1935 // Landing detection code 2085 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
1936 2086 if (AgentControlStopActive)
1937 // Are the landing controls requirements filled?
1938 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1939 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1940
1941 //m_log.Debug("[CONTROL]: " +flags);
1942 // Applies a satisfying roll effect to the avatar when flying.
1943 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
1944 {
1945 ApplyFlyingRoll(
1946 FLY_ROLL_RADIANS_PER_UPDATE,
1947 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
1948 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
1949 }
1950 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
1951 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1952 { 2087 {
1953 ApplyFlyingRoll( 2088 agent_control_v3 = Vector3.Zero;
1954 -FLY_ROLL_RADIANS_PER_UPDATE,
1955 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
1956 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
1957 } 2089 }
1958 else 2090 else
1959 { 2091 {
1960 if (m_AngularVelocity.Z != 0) 2092 // Landing detection code
1961 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
1962 }
1963 2093
1964 if (Flying && IsColliding && controlland) 2094 // Are the landing controls requirements filled?
1965 { 2095 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1966 // nesting this check because LengthSquared() is expensive and we don't 2096 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1967 // want to do it every step when flying. 2097
1968 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) 2098 //m_log.Debug("[CONTROL]: " +flags);
1969 StopFlying(); 2099 // Applies a satisfying roll effect to the avatar when flying.
2100 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2101 {
2102 ApplyFlyingRoll(
2103 FLY_ROLL_RADIANS_PER_UPDATE,
2104 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2105 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2106 }
2107 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2108 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2109 {
2110 ApplyFlyingRoll(
2111 -FLY_ROLL_RADIANS_PER_UPDATE,
2112 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2113 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2114 }
2115 else
2116 {
2117 if (m_AngularVelocity.Z != 0)
2118 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2119 }
2120
2121 if (Flying && IsColliding && controlland)
2122 {
2123 // nesting this check because LengthSquared() is expensive and we don't
2124 // want to do it every step when flying.
2125 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2126 StopFlying();
2127 }
1970 } 2128 }
1971 } 2129 }
1972 2130
2131// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2132
1973 // If the agent update does move the avatar, then calculate the force ready for the velocity update, 2133 // If the agent update does move the avatar, then calculate the force ready for the velocity update,
1974 // which occurs later in the main scene loop 2134 // which occurs later in the main scene loop
1975 if (update_movementflag || (update_rotation && DCFlagKeyPressed)) 2135 // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
2136 // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update
2137 // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the
2138 // avatar location in place).
2139 if (update_movementflag
2140 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
1976 { 2141 {
1977// m_log.DebugFormat( 2142// if (update_movementflag || !AgentControlStopActive || MovementFlag != 0)
1978// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", 2143// {
1979// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); 2144// m_log.DebugFormat(
2145// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}",
2146// m_scene.RegionInfo.RegionName, agent_control_v3, Name,
2147// update_movementflag, MovementFlag, update_rotation);
1980 2148
1981 AddNewMovement(agent_control_v3); 2149 float speedModifier;
2150
2151 if (AgentControlStopActive)
2152 speedModifier = AgentControlStopSlowWhilstMoving;
2153 else
2154 speedModifier = 1;
2155
2156 AddNewMovement(agent_control_v3, speedModifier);
2157// }
1982 } 2158 }
1983// else 2159// else
1984// { 2160// {
@@ -1991,15 +2167,86 @@ namespace OpenSim.Region.Framework.Scenes
1991// } 2167// }
1992 2168
1993 if (update_movementflag && ParentID == 0) 2169 if (update_movementflag && ParentID == 0)
2170 {
2171// m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
1994 Animator.UpdateMovementAnimations(); 2172 Animator.UpdateMovementAnimations();
2173 }
1995 2174
1996 SendControlsToScripts(flagsForScripts); 2175 SendControlsToScripts(flagsForScripts);
1997 } 2176 }
1998 2177
2178 // We need to send this back to the client in order to see the edit beams
2179 if ((State & (uint)AgentState.Editing) != 0)
2180 ControllingClient.SendAgentTerseUpdate(this);
2181
1999 m_scene.EventManager.TriggerOnClientMovement(this); 2182 m_scene.EventManager.TriggerOnClientMovement(this);
2000 TriggerScenePresenceUpdated();
2001 } 2183 }
2002 2184
2185
2186 /// <summary>
2187 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
2188 /// </summary>
2189 private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2190 {
2191 //m_log.DebugFormat(
2192 // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
2193 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2194
2195 if (IsChildAgent)
2196 {
2197 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2198 return;
2199 }
2200
2201 ++m_movementUpdateCount;
2202 if (m_movementUpdateCount < 1)
2203 m_movementUpdateCount = 1;
2204
2205// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2206
2207 // Camera location in world. We'll need to raytrace
2208 // from this location from time to time.
2209 CameraPosition = agentData.CameraCenter;
2210 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
2211 {
2212 ReprioritizeUpdates();
2213 m_lastCameraPosition = CameraPosition;
2214 }
2215
2216 // Use these three vectors to figure out what the agent is looking at
2217 // Convert it to a Matrix and/or Quaternion
2218 CameraAtAxis = agentData.CameraAtAxis;
2219 CameraLeftAxis = agentData.CameraLeftAxis;
2220 CameraUpAxis = agentData.CameraUpAxis;
2221
2222 // The Agent's Draw distance setting
2223 // When we get to the point of re-computing neighbors everytime this
2224 // changes, then start using the agent's drawdistance rather than the
2225 // region's draw distance.
2226 // DrawDistance = agentData.Far;
2227 DrawDistance = Scene.DefaultDrawDistance;
2228
2229 // Check if Client has camera in 'follow cam' or 'build' mode.
2230 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2231
2232 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
2233 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
2234
2235
2236 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
2237 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2238 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2239 {
2240 if (m_followCamAuto)
2241 {
2242 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2243 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2244 }
2245 }
2246
2247 TriggerScenePresenceUpdated();
2248 }
2249
2003 /// <summary> 2250 /// <summary>
2004 /// Calculate an update to move the presence to the set target. 2251 /// Calculate an update to move the presence to the set target.
2005 /// </summary> 2252 /// </summary>
@@ -2252,17 +2499,13 @@ namespace OpenSim.Region.Framework.Scenes
2252 { 2499 {
2253// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 2500// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
2254 2501
2502 bool satOnObject = IsSatOnObject;
2503 SceneObjectPart part = ParentPart;
2255 SitGround = false; 2504 SitGround = false;
2256 2505
2257/* move this down so avatar gets physical in the new position and not where it is siting 2506 if (satOnObject)
2258 if (PhysicsActor == null)
2259 AddToPhysicalScene(false);
2260 */
2261
2262 if (ParentID != 0)
2263 { 2507 {
2264 PrevSitOffset = m_pos; // Save sit offset 2508 PrevSitOffset = m_pos; // Save sit offset
2265 SceneObjectPart part = ParentPart;
2266 UnRegisterSeatControls(part.ParentGroup.UUID); 2509 UnRegisterSeatControls(part.ParentGroup.UUID);
2267 2510
2268 TaskInventoryDictionary taskIDict = part.TaskInventory; 2511 TaskInventoryDictionary taskIDict = part.TaskInventory;
@@ -2281,34 +2524,71 @@ namespace OpenSim.Region.Framework.Scenes
2281 } 2524 }
2282 2525
2283 part.ParentGroup.DeleteAvatar(UUID); 2526 part.ParentGroup.DeleteAvatar(UUID);
2284// ParentPosition = part.GetWorldPosition(); 2527 Vector3 sitPartWorldPosition = part.GetWorldPosition();
2285 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 2528 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2286 2529
2287// m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
2288// ParentPosition = Vector3.Zero;
2289 m_pos = part.AbsolutePosition + (m_pos * part.GetWorldRotation()) + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
2290 if (part.SitTargetAvatar == UUID)
2291 m_bodyRot = part.GetWorldRotation() * part.SitTargetOrientation;
2292
2293 ParentID = 0; 2530 ParentID = 0;
2294 ParentPart = null; 2531 ParentPart = null;
2295 2532
2296 if (PhysicsActor == null) 2533 Quaternion standRotation;
2297 AddToPhysicalScene(false);
2298 2534
2535 if (part.SitTargetAvatar == UUID)
2536 {
2537 standRotation = part.GetWorldRotation();
2538
2539 if (!part.IsRoot)
2540 standRotation = standRotation * part.SitTargetOrientation;
2541// standRotation = part.RotationOffset * part.SitTargetOrientation;
2542// else
2543// standRotation = part.SitTargetOrientation;
2544
2545 }
2546 else
2547 {
2548 standRotation = Rotation;
2549 }
2550
2551 //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
2552 //Vector3 standPos = ParentPosition;
2553
2554// Vector3 standPositionAdjustment
2555// = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f);
2556 Vector3 adjustmentForSitPosition = part.SitTargetPosition * part.GetWorldRotation();
2557
2558 // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than
2559 // hardcoding here.
2560 Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation;
2561
2562 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPosition + adjustmentForSitPose;
2563
2564// m_log.DebugFormat(
2565// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}",
2566// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
2567
2568 Rotation = standRotation;
2569 AbsolutePosition = standPos;
2570 }
2571
2572 // We need to wait until we have calculated proper stand positions before sitting up the physical
2573 // avatar to avoid race conditions.
2574 if (PhysicsActor == null)
2575 AddToPhysicalScene(false);
2576
2577 if (satOnObject)
2578 {
2299 SendAvatarDataToAllAgents(); 2579 SendAvatarDataToAllAgents();
2300 m_requestedSitTargetID = 0; 2580 m_requestedSitTargetID = 0;
2301 2581
2302 part.RemoveSittingAvatar(UUID); 2582 part.RemoveSittingAvatar(UUID);
2303 2583
2304 if (part != null) 2584 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2305 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2306 } 2585 }
2307 2586
2308 else if (PhysicsActor == null) 2587 else if (PhysicsActor == null)
2309 AddToPhysicalScene(false); 2588 AddToPhysicalScene(false);
2310 2589
2311 Animator.TrySetMovementAnimation("STAND"); 2590 Animator.TrySetMovementAnimation("STAND");
2591 TriggerScenePresenceUpdated();
2312 } 2592 }
2313 2593
2314 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) 2594 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
@@ -2359,7 +2639,6 @@ namespace OpenSim.Region.Framework.Scenes
2359 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2639 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2360 2640
2361 bool canSit = false; 2641 bool canSit = false;
2362 Vector3 pos = part.AbsolutePosition + offset;
2363 2642
2364 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2643 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2365 { 2644 {
@@ -2369,6 +2648,17 @@ namespace OpenSim.Region.Framework.Scenes
2369 2648
2370 offset = part.SitTargetPosition; 2649 offset = part.SitTargetPosition;
2371 sitOrientation = part.SitTargetOrientation; 2650 sitOrientation = part.SitTargetOrientation;
2651
2652 if (!part.IsRoot)
2653 {
2654 // m_log.DebugFormat("Old sit orient {0}", sitOrientation);
2655 sitOrientation = part.RotationOffset * sitOrientation;
2656 // m_log.DebugFormat("New sit orient {0}", sitOrientation);
2657// m_log.DebugFormat("Old sit offset {0}", offset);
2658 offset = offset * part.RotationOffset;
2659// m_log.DebugFormat("New sit offset {0}", offset);
2660 }
2661
2372 canSit = true; 2662 canSit = true;
2373 } 2663 }
2374 else 2664 else
@@ -2376,9 +2666,10 @@ namespace OpenSim.Region.Framework.Scenes
2376 if (PhysicsSit(part,offset)) // physics engine 2666 if (PhysicsSit(part,offset)) // physics engine
2377 return; 2667 return;
2378 2668
2669 Vector3 pos = part.AbsolutePosition + offset;
2670
2379 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 2671 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
2380 { 2672 {
2381
2382 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 2673 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
2383 canSit = true; 2674 canSit = true;
2384 } 2675 }
@@ -2404,10 +2695,14 @@ namespace OpenSim.Region.Framework.Scenes
2404 cameraEyeOffset = part.GetCameraEyeOffset(); 2695 cameraEyeOffset = part.GetCameraEyeOffset();
2405 forceMouselook = part.GetForceMouselook(); 2696 forceMouselook = part.GetForceMouselook();
2406 2697
2698 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2699 // being sat upon.
2700 offset += part.OffsetPosition;
2701
2407 ControllingClient.SendSitResponse( 2702 ControllingClient.SendSitResponse(
2408 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2703 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2409 2704
2410 m_requestedSitTargetUUID = targetID; 2705 m_requestedSitTargetUUID = part.UUID;
2411 2706
2412 HandleAgentSit(ControllingClient, UUID); 2707 HandleAgentSit(ControllingClient, UUID);
2413 2708
@@ -2435,7 +2730,7 @@ namespace OpenSim.Region.Framework.Scenes
2435 if (part != null) 2730 if (part != null)
2436 { 2731 {
2437 m_requestedSitTargetID = part.LocalId; 2732 m_requestedSitTargetID = part.LocalId;
2438 m_requestedSitTargetUUID = targetID; 2733 m_requestedSitTargetUUID = part.UUID;
2439 2734
2440 } 2735 }
2441 else 2736 else
@@ -2554,6 +2849,9 @@ namespace OpenSim.Region.Framework.Scenes
2554 2849
2555 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 2850 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2556 { 2851 {
2852 if (IsChildAgent)
2853 return;
2854
2557 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2855 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2558 2856
2559 if (part != null) 2857 if (part != null)
@@ -2603,24 +2901,40 @@ namespace OpenSim.Region.Framework.Scenes
2603 Vector3 up = new Vector3((float)x, (float)y, (float)z); 2901 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2604 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; 2902 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2605 2903
2606 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; 2904 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2905 Quaternion newRot;
2906
2907 if (part.IsRoot)
2908 {
2909 newRot = sitTargetOrient;
2910 }
2911 else
2912 {
2913 newPos = newPos * part.RotationOffset;
2914 newRot = part.RotationOffset * sitTargetOrient;
2915 }
2916
2917 newPos += part.OffsetPosition;
2918
2919 m_pos = newPos;
2920 Rotation = newRot;
2607 2921
2608// m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
2609 Rotation = sitTargetOrient;
2610// ParentPosition = part.AbsolutePosition; 2922// ParentPosition = part.AbsolutePosition;
2611 part.ParentGroup.AddAvatar(UUID);
2612 } 2923 }
2613 else 2924 else
2614 { 2925 {
2615 m_pos -= part.AbsolutePosition; 2926 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2927 // being sat upon.
2928 m_pos -= part.GroupPosition;
2929
2616// ParentPosition = part.AbsolutePosition; 2930// ParentPosition = part.AbsolutePosition;
2617 part.ParentGroup.AddAvatar(UUID);
2618 2931
2619// m_log.DebugFormat( 2932// m_log.DebugFormat(
2620// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2933// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
2621// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 2934// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
2622 } 2935 }
2623 2936
2937 part.ParentGroup.AddAvatar(UUID);
2624 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2938 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2625 ParentID = m_requestedSitTargetID; 2939 ParentID = m_requestedSitTargetID;
2626 m_AngularVelocity = Vector3.Zero; 2940 m_AngularVelocity = Vector3.Zero;
@@ -2634,14 +2948,19 @@ namespace OpenSim.Region.Framework.Scenes
2634 } 2948 }
2635 Animator.TrySetMovementAnimation(sitAnimation); 2949 Animator.TrySetMovementAnimation(sitAnimation);
2636 SendAvatarDataToAllAgents(); 2950 SendAvatarDataToAllAgents();
2951 TriggerScenePresenceUpdated();
2637 } 2952 }
2638 } 2953 }
2639 2954
2640 public void HandleAgentSitOnGround() 2955 public void HandleAgentSitOnGround()
2641 { 2956 {
2957 if (IsChildAgent)
2958 return;
2959
2642// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 2960// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
2643 m_AngularVelocity = Vector3.Zero; 2961 m_AngularVelocity = Vector3.Zero;
2644 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 2962 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
2963 TriggerScenePresenceUpdated();
2645 SitGround = true; 2964 SitGround = true;
2646 RemoveFromPhysicalScene(); 2965 RemoveFromPhysicalScene();
2647 } 2966 }
@@ -2658,11 +2977,13 @@ namespace OpenSim.Region.Framework.Scenes
2658 public void HandleStartAnim(IClientAPI remoteClient, UUID animID) 2977 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
2659 { 2978 {
2660 Animator.AddAnimation(animID, UUID.Zero); 2979 Animator.AddAnimation(animID, UUID.Zero);
2980 TriggerScenePresenceUpdated();
2661 } 2981 }
2662 2982
2663 public void HandleStopAnim(IClientAPI remoteClient, UUID animID) 2983 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
2664 { 2984 {
2665 Animator.RemoveAnimation(animID, false); 2985 Animator.RemoveAnimation(animID, false);
2986 TriggerScenePresenceUpdated();
2666 } 2987 }
2667 2988
2668 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) 2989 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
@@ -2676,10 +2997,13 @@ namespace OpenSim.Region.Framework.Scenes
2676 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 2997 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2677 /// </summary> 2998 /// </summary>
2678 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2999 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2679 public void AddNewMovement(Vector3 vec) 3000 /// <param name="thisAddSpeedModifier">
3001 /// Optional additional speed modifier for this particular add. Default is 1</param>
3002 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1)
2680 { 3003 {
2681// m_log.DebugFormat( 3004// m_log.DebugFormat(
2682// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); 3005// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3006// vec, Rotation, thisAddSpeedModifier, Name);
2683 3007
2684 Vector3 direc = vec * Rotation; 3008 Vector3 direc = vec * Rotation;
2685 direc.Normalize(); 3009 direc.Normalize();
@@ -2697,7 +3021,7 @@ namespace OpenSim.Region.Framework.Scenes
2697 if ((vec.Z == 0f) && !Flying) 3021 if ((vec.Z == 0f) && !Flying)
2698 direc.Z = 0f; // Prevent camera WASD up. 3022 direc.Z = 0f; // Prevent camera WASD up.
2699 3023
2700 direc *= 0.03f * 128f * SpeedModifier; 3024 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
2701 3025
2702// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3026// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
2703 3027
@@ -2843,6 +3167,7 @@ namespace OpenSim.Region.Framework.Scenes
2843 lastTerseUpdateToAllClientsTick = currentTick; 3167 lastTerseUpdateToAllClientsTick = currentTick;
2844 lastPositionSentToAllClients = OffsetPosition; 3168 lastPositionSentToAllClients = OffsetPosition;
2845 3169
3170// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
2846 m_scene.ForEachClient(SendTerseUpdateToClient); 3171 m_scene.ForEachClient(SendTerseUpdateToClient);
2847 } 3172 }
2848 TriggerScenePresenceUpdated(); 3173 TriggerScenePresenceUpdated();
@@ -2880,11 +3205,12 @@ namespace OpenSim.Region.Framework.Scenes
2880 SendOtherAgentsAppearanceToMe(); 3205 SendOtherAgentsAppearanceToMe();
2881 3206
2882 EntityBase[] entities = Scene.Entities.GetEntities(); 3207 EntityBase[] entities = Scene.Entities.GetEntities();
2883 foreach(EntityBase e in entities) 3208 foreach (EntityBase e in entities)
2884 { 3209 {
2885 if (e != null && e is SceneObjectGroup) 3210 if (e != null && e is SceneObjectGroup)
2886 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3211 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
2887 } 3212 }
3213
2888 }); 3214 });
2889 } 3215 }
2890 3216
@@ -2919,12 +3245,14 @@ namespace OpenSim.Region.Framework.Scenes
2919 // again here... this comes after the cached appearance check because the avatars 3245 // again here... this comes after the cached appearance check because the avatars
2920 // appearance goes into the avatar update packet 3246 // appearance goes into the avatar update packet
2921 SendAvatarDataToAllAgents(); 3247 SendAvatarDataToAllAgents();
3248
3249 // This invocation always shows up in the viewer logs as an error. Is it needed?
2922 SendAppearanceToAgent(this); 3250 SendAppearanceToAgent(this);
2923 3251
2924 // If we are using the the cached appearance then send it out to everyone 3252 // If we are using the the cached appearance then send it out to everyone
2925 if (cachedappearance) 3253 if (cachedappearance)
2926 { 3254 {
2927 m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); 3255 m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
2928 3256
2929 // If the avatars baked textures are all in the cache, then we have a 3257 // If the avatars baked textures are all in the cache, then we have a
2930 // complete appearance... send it out, if not, then we'll send it when 3258 // complete appearance... send it out, if not, then we'll send it when
@@ -3079,11 +3407,10 @@ namespace OpenSim.Region.Framework.Scenes
3079 } 3407 }
3080 3408
3081 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 3409 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
3082 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || 3410 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
3083 Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
3084 { 3411 {
3085 m_lastChildAgentUpdatePosition = AbsolutePosition; 3412 m_lastChildAgentUpdatePosition = AbsolutePosition;
3086 m_lastChildAgentUpdateCamPosition = CameraPosition; 3413// m_lastChildAgentUpdateCamPosition = CameraPosition;
3087 3414
3088 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3415 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3089 cadu.ActiveGroupID = UUID.Zero.Guid; 3416 cadu.ActiveGroupID = UUID.Zero.Guid;
@@ -3110,7 +3437,7 @@ namespace OpenSim.Region.Framework.Scenes
3110 cadu.Velocity = Velocity; 3437 cadu.Velocity = Velocity;
3111 3438
3112 AgentPosition agentpos = new AgentPosition(); 3439 AgentPosition agentpos = new AgentPosition();
3113 agentpos.CopyFrom(cadu); 3440 agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3114 3441
3115 // Let's get this out of the update loop 3442 // Let's get this out of the update loop
3116 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); 3443 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); });
@@ -3294,11 +3621,6 @@ namespace OpenSim.Region.Framework.Scenes
3294 } 3621 }
3295 } 3622 }
3296 3623
3297 public void RestoreInCurrentScene()
3298 {
3299 AddToPhysicalScene(false); // not exactly false
3300 }
3301
3302 public void Reset() 3624 public void Reset()
3303 { 3625 {
3304// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); 3626// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
@@ -3348,10 +3670,12 @@ namespace OpenSim.Region.Framework.Scenes
3348 if (byebyeRegions.Count > 0) 3670 if (byebyeRegions.Count > 0)
3349 { 3671 {
3350 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 3672 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
3351 Util.FireAndForget(delegate 3673
3352 { 3674 AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
3353 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); 3675 string auth = string.Empty;
3354 }); 3676 if (acd != null)
3677 auth = acd.SessionID.ToString();
3678 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3355 } 3679 }
3356 3680
3357 foreach (ulong handle in byebyeRegions) 3681 foreach (ulong handle in byebyeRegions)
@@ -3392,7 +3716,7 @@ namespace OpenSim.Region.Framework.Scenes
3392 3716
3393 #region Child Agent Updates 3717 #region Child Agent Updates
3394 3718
3395 public void ChildAgentDataUpdate(AgentData cAgentData) 3719 public void UpdateChildAgent(AgentData cAgentData)
3396 { 3720 {
3397// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); 3721// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
3398 if (!IsChildAgent) 3722 if (!IsChildAgent)
@@ -3402,15 +3726,17 @@ namespace OpenSim.Region.Framework.Scenes
3402 } 3726 }
3403 3727
3404 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 3728 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3729
3405 private void RaiseUpdateThrottles() 3730 private void RaiseUpdateThrottles()
3406 { 3731 {
3407 m_scene.EventManager.TriggerThrottleUpdate(this); 3732 m_scene.EventManager.TriggerThrottleUpdate(this);
3408 } 3733 }
3734
3409 /// <summary> 3735 /// <summary>
3410 /// This updates important decision making data about a child agent 3736 /// This updates important decision making data about a child agent
3411 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 3737 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
3412 /// </summary> 3738 /// </summary>
3413 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) 3739 public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
3414 { 3740 {
3415 if (!IsChildAgent) 3741 if (!IsChildAgent)
3416 return; 3742 return;
@@ -3452,6 +3778,7 @@ namespace OpenSim.Region.Framework.Scenes
3452 3778
3453 cAgent.AgentID = UUID; 3779 cAgent.AgentID = UUID;
3454 cAgent.RegionID = Scene.RegionInfo.RegionID; 3780 cAgent.RegionID = Scene.RegionInfo.RegionID;
3781 cAgent.SessionID = ControllingClient.SessionId;
3455 3782
3456 cAgent.Position = AbsolutePosition; 3783 cAgent.Position = AbsolutePosition;
3457 cAgent.Velocity = m_velocity; 3784 cAgent.Velocity = m_velocity;
@@ -3517,7 +3844,8 @@ namespace OpenSim.Region.Framework.Scenes
3517 3844
3518 private void CopyFrom(AgentData cAgent) 3845 private void CopyFrom(AgentData cAgent)
3519 { 3846 {
3520 m_originRegionID = cAgent.RegionID; 3847 lock (m_originRegionIDAccessLock)
3848 m_originRegionID = cAgent.RegionID;
3521 3849
3522 m_callbackURI = cAgent.CallbackURI; 3850 m_callbackURI = cAgent.CallbackURI;
3523// m_log.DebugFormat( 3851// m_log.DebugFormat(
@@ -3611,8 +3939,6 @@ namespace OpenSim.Region.Framework.Scenes
3611 { 3939 {
3612 Vector3 force = m_forceToApply.Value; 3940 Vector3 force = m_forceToApply.Value;
3613 3941
3614 Updated = true;
3615
3616 Velocity = force; 3942 Velocity = force;
3617 3943
3618 m_forceToApply = null; 3944 m_forceToApply = null;
@@ -3694,7 +4020,8 @@ namespace OpenSim.Region.Framework.Scenes
3694 4020
3695// if (m_updateCount > 0) 4021// if (m_updateCount > 0)
3696// { 4022// {
3697 Animator.UpdateMovementAnimations(); 4023 if (Animator.UpdateMovementAnimations())
4024 TriggerScenePresenceUpdated();
3698// m_updateCount--; 4025// m_updateCount--;
3699// } 4026// }
3700 4027
@@ -3858,6 +4185,7 @@ namespace OpenSim.Region.Framework.Scenes
3858// Animator.Close(); 4185// Animator.Close();
3859 Animator = null; 4186 Animator = null;
3860 4187
4188 LifecycleState = ScenePresenceState.Removed;
3861 } 4189 }
3862 4190
3863 public void AddAttachment(SceneObjectGroup gobj) 4191 public void AddAttachment(SceneObjectGroup gobj)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
new file mode 100644
index 0000000..cae7fe5
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
@@ -0,0 +1,113 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29
30namespace OpenSim.Region.Framework.Scenes
31{
32 /// <summary>
33 /// The possible states that a scene presence can be in. This is currently orthagonal to whether a scene presence
34 /// is root or child.
35 /// </summary>
36 /// <remarks>
37 /// This is a state machine.
38 ///
39 /// [Entry] => Running
40 /// Running => PreRemove, Removing
41 /// PreRemove => Running, Removing
42 /// Removing => Removed
43 ///
44 /// All other methods should only see the scene presence in running state - this is the normal operational state
45 /// Removed state occurs when the presence has been removed. This is the end state with no exit.
46 /// </remarks>
47 public enum ScenePresenceState
48 {
49 Running, // Normal operation state. The scene presence is available.
50 PreRemove, // The presence is due to be removed but can still be returning to running.
51 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient.
52 Removed, // The presence has been removed from the scene and is effectively dead.
53 // There is no exit from this state.
54 }
55
56 internal class ScenePresenceStateMachine
57 {
58 private ScenePresence m_sp;
59 private ScenePresenceState m_state;
60
61 internal ScenePresenceStateMachine(ScenePresence sp)
62 {
63 m_sp = sp;
64 m_state = ScenePresenceState.Running;
65 }
66
67 internal ScenePresenceState GetState()
68 {
69 return m_state;
70 }
71
72 /// <summary>
73 /// Updates the state of an agent that is already in transit.
74 /// </summary>
75 /// <param name='id'></param>
76 /// <param name='newState'></param>
77 /// <returns></returns>
78 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
79 internal void SetState(ScenePresenceState newState)
80 {
81 bool transitionOkay = false;
82
83 lock (this)
84 {
85 if (newState == m_state)
86 return;
87 else if (newState == ScenePresenceState.Running && m_state == ScenePresenceState.PreRemove)
88 transitionOkay = true;
89 else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running)
90 transitionOkay = true;
91 else if (newState == ScenePresenceState.Removing)
92 {
93 if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove)
94 transitionOkay = true;
95 }
96 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
97 transitionOkay = true;
98 }
99
100 if (!transitionOkay)
101 {
102 throw new Exception(
103 string.Format(
104 "Scene presence {0} is not allowed to move from state {1} to new state {2} in {3}",
105 m_sp.Name, m_state, newState, m_sp.Scene.Name));
106 }
107 else
108 {
109 m_state = newState;
110 }
111 }
112 }
113} \ 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 ce4fb40..5372360 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("AttachedPos", ProcessAttachedPos);
368 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs); 369 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs);
369 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); 370 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation);
370 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); 371 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem);
@@ -443,6 +444,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
443 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd); 444 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd);
444 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow); 445 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow);
445 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale); 446 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale);
447 m_ShapeXmlProcessors.Add("LastAttachPoint", ProcessShpLastAttach);
446 m_ShapeXmlProcessors.Add("State", ProcessShpState); 448 m_ShapeXmlProcessors.Add("State", ProcessShpState);
447 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape); 449 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape);
448 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape); 450 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape);
@@ -798,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
798 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); 800 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty);
799 } 801 }
800 802
803 private static void ProcessAttachedPos(SceneObjectPart obj, XmlTextReader reader)
804 {
805 obj.AttachedPos = Util.ReadVector(reader, "AttachedPos");
806 }
807
801 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) 808 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader)
802 { 809 {
803 obj.DynAttrs.ReadXml(reader); 810 obj.DynAttrs.ReadXml(reader);
@@ -1099,6 +1106,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1099 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); 1106 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty);
1100 } 1107 }
1101 1108
1109 private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlTextReader reader)
1110 {
1111 shp.LastAttachPoint = (byte)reader.ReadElementContentAsInt("LastAttachPoint", String.Empty);
1112 }
1113
1102 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) 1114 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader)
1103 { 1115 {
1104 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape"); 1116 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape");
@@ -1267,7 +1279,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1267 1279
1268 WriteUUID(writer, "CreatorID", sop.CreatorID, options); 1280 WriteUUID(writer, "CreatorID", sop.CreatorID, options);
1269 1281
1270 if (sop.CreatorData != null && sop.CreatorData != string.Empty) 1282 if (!string.IsNullOrEmpty(sop.CreatorData))
1271 writer.WriteElementString("CreatorData", sop.CreatorData); 1283 writer.WriteElementString("CreatorData", sop.CreatorData);
1272 else if (options.ContainsKey("home")) 1284 else if (options.ContainsKey("home"))
1273 { 1285 {
@@ -1345,8 +1357,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1345 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); 1357 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString());
1346 if (sop.MediaUrl != null) 1358 if (sop.MediaUrl != null)
1347 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); 1359 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
1360 WriteVector(writer, "AttachedPos", sop.AttachedPos);
1348 1361
1349 if (sop.DynAttrs.Count > 0) 1362 if (sop.DynAttrs.CountNamespaces > 0)
1350 { 1363 {
1351 writer.WriteStartElement("DynAttrs"); 1364 writer.WriteStartElement("DynAttrs");
1352 sop.DynAttrs.WriteXml(writer); 1365 sop.DynAttrs.WriteXml(writer);
@@ -1451,7 +1464,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1451 1464
1452 WriteUUID(writer, "CreatorID", item.CreatorID, options); 1465 WriteUUID(writer, "CreatorID", item.CreatorID, options);
1453 1466
1454 if (item.CreatorData != null && item.CreatorData != string.Empty) 1467 if (!string.IsNullOrEmpty(item.CreatorData))
1455 writer.WriteElementString("CreatorData", item.CreatorData); 1468 writer.WriteElementString("CreatorData", item.CreatorData);
1456 else if (options.ContainsKey("home")) 1469 else if (options.ContainsKey("home"))
1457 { 1470 {
@@ -1539,6 +1552,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1539 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); 1552 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
1540 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); 1553 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
1541 writer.WriteElementString("State", shp.State.ToString()); 1554 writer.WriteElementString("State", shp.State.ToString());
1555 writer.WriteElementString("LastAttachPoint", shp.LastAttachPoint.ToString());
1542 1556
1543 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); 1557 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
1544 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options); 1558 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options);
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 5398ab9..bf32251 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -290,6 +290,9 @@ namespace OpenSim.Region.Framework.Scenes
290 290
291 private void statsHeartBeat(object sender, EventArgs e) 291 private void statsHeartBeat(object sender, EventArgs e)
292 { 292 {
293 if (!m_scene.Active)
294 return;
295
293 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23]; 296 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23];
294 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); 297 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
295 298
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 9557cd0..95b30d5 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -33,7 +33,9 @@ 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.EntityTransfer;
36using OpenSim.Region.CoreModules.Framework.InventoryAccess; 37using OpenSim.Region.CoreModules.Framework.InventoryAccess;
38using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
37using OpenSim.Region.CoreModules.World.Permissions; 39using OpenSim.Region.CoreModules.World.Permissions;
38using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
@@ -52,6 +54,24 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 [TestFixture] 54 [TestFixture]
53 public class SceneObjectDeRezTests : OpenSimTestCase 55 public class SceneObjectDeRezTests : OpenSimTestCase
54 { 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 // This facility was added after the original async delete tests were written, so it may be possible now
62 // to not bother explicitly disabling their async (since everything will be running sync).
63 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
64 }
65
66 [TestFixtureTearDown]
67 public void TearDown()
68 {
69 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
70 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
71 // tests really shouldn't).
72 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
73 }
74
55 /// <summary> 75 /// <summary>
56 /// Test deleting an object from a scene. 76 /// Test deleting an object from a scene.
57 /// </summary> 77 /// </summary>
@@ -59,7 +79,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
59 public void TestDeRezSceneObject() 79 public void TestDeRezSceneObject()
60 { 80 {
61 TestHelpers.InMethod(); 81 TestHelpers.InMethod();
62// log4net.Config.XmlConfigurator.Configure();
63 82
64 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 83 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
65 84
@@ -73,32 +92,77 @@ namespace OpenSim.Region.Framework.Scenes.Tests
73 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 92 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
74 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 93 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
75 sogd.Enabled = false; 94 sogd.Enabled = false;
76 95
77 SceneObjectPart part 96 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", userId);
78 = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); 97 uint soLocalId = so.LocalId;
79 part.Name = "obj1";
80 scene.AddNewSceneObject(new SceneObjectGroup(part), false);
81 98
82 List<uint> localIds = new List<uint>(); 99 List<uint> localIds = new List<uint>();
83 localIds.Add(part.LocalId); 100 localIds.Add(so.LocalId);
84 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); 101 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero);
85 102
86 // Check that object isn't deleted until we crank the sogd handle. 103 // Check that object isn't deleted until we crank the sogd handle.
87 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 104 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
88 Assert.That(retrievedPart, Is.Not.Null); 105 Assert.That(retrievedPart, Is.Not.Null);
89 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); 106 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False);
90 107
91 sogd.InventoryDeQueueAndDelete(); 108 sogd.InventoryDeQueueAndDelete();
92 109
93 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId); 110 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
94 Assert.That(retrievedPart2, Is.Null); 111 Assert.That(retrievedPart2, Is.Null);
112 }
113
114 /// <summary>
115 /// Test that child and root agents correctly receive KillObject notifications.
116 /// </summary>
117 [Test]
118 public void TestDeRezSceneObjectToAgents()
119 {
120 TestHelpers.InMethod();
121// TestHelpers.EnableLogging();
122
123 SceneHelpers sh = new SceneHelpers();
124 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
125 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
126
127 // We need this so that the creation of the root client for userB in sceneB can trigger the creation of a child client in sceneA
128 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
129 EntityTransferModule etmB = new EntityTransferModule();
130 IConfigSource config = new IniConfigSource();
131 IConfig modulesConfig = config.AddConfig("Modules");
132 modulesConfig.Set("EntityTransferModule", etmB.Name);
133 modulesConfig.Set("SimulationServices", lscm.Name);
134 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
135 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
136
137 // We need this for derez
138 //SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule());
139
140 UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, "");
141 UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, "");
142
143 TestClient clientA = (TestClient)SceneHelpers.AddScenePresence(sceneA, uaA).ControllingClient;
144
145 // This is the more long-winded route we have to take to get a child client created for userB in sceneA
146 // rather than just calling AddScenePresence() as for userA
147 AgentCircuitData acd = SceneHelpers.GenerateAgentData(uaB);
148 TestClient clientB = new TestClient(acd, sceneB);
149 List<TestClient> childClientsB = new List<TestClient>();
150 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(clientB, childClientsB);
151
152 SceneHelpers.AddScenePresence(sceneB, clientB, acd);
153
154 SceneObjectGroup so = SceneHelpers.AddSceneObject(sceneA);
155 uint soLocalId = so.LocalId;
156
157 sceneA.DeleteSceneObject(so, false);
95 } 158 }
96 159
97 /// <summary> 160 /// <summary>
98 /// Test deleting an object from a scene where the deleter is not the owner 161 /// Test deleting an object from a scene where the deleter is not the owner
99 /// </summary> 162 /// </summary>
100 /// 163 /// <remarks>
101 /// This test assumes that the deleter is not a god. 164 /// This test assumes that the deleter is not a god.
165 /// </remarks>
102 [Test] 166 [Test]
103 public void TestDeRezSceneObjectNotOwner() 167 public void TestDeRezSceneObjectNotOwner()
104 { 168 {
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index bbfbbfc..1ff1329 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -111,6 +111,45 @@ namespace OpenSim.Region.Framework.Scenes.Tests
111 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1)); 111 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
112 } 112 }
113 113
114 /// <summary>
115 /// Test that duplicate complete movement calls are ignored.
116 /// </summary>
117 /// <remarks>
118 /// If duplicate calls are not ignored then there is a risk of race conditions or other unexpected effects.
119 /// </remarks>
120 [Test]
121 public void TestDupeCompleteMovementCalls()
122 {
123 TestHelpers.InMethod();
124// TestHelpers.EnableLogging();
125
126 UUID spUuid = TestHelpers.ParseTail(0x1);
127
128 TestScene scene = new SceneHelpers().SetupScene();
129
130 int makeRootAgentEvents = 0;
131 scene.EventManager.OnMakeRootAgent += spi => makeRootAgentEvents++;
132
133 ScenePresence sp = SceneHelpers.AddScenePresence(scene, spUuid);
134
135 Assert.That(makeRootAgentEvents, Is.EqualTo(1));
136
137 // Normally these would be invoked by a CompleteMovement message coming in to the UDP stack. But for
138 // convenience, here we will invoke it manually.
139 sp.CompleteMovement(sp.ControllingClient, true);
140
141 Assert.That(makeRootAgentEvents, Is.EqualTo(1));
142
143 // Check rest of exepcted parameters.
144 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
145 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
146
147 Assert.That(sp.IsChildAgent, Is.False);
148 Assert.That(sp.UUID, Is.EqualTo(spUuid));
149
150 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
151 }
152
114 [Test] 153 [Test]
115 public void TestCreateDuplicateRootScenePresence() 154 public void TestCreateDuplicateRootScenePresence()
116 { 155 {
@@ -119,7 +158,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
119 158
120 UUID spUuid = TestHelpers.ParseTail(0x1); 159 UUID spUuid = TestHelpers.ParseTail(0x1);
121 160
161 // The etm is only invoked by this test to check whether an agent is still in transit if there is a dupe
162 EntityTransferModule etm = new EntityTransferModule();
163
164 IConfigSource config = new IniConfigSource();
165 IConfig modulesConfig = config.AddConfig("Modules");
166 modulesConfig.Set("EntityTransferModule", etm.Name);
167 IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
168
169 // In order to run a single threaded regression test we do not want the entity transfer module waiting
170 // for a callback from the destination scene before removing its avatar data.
171 entityTransferConfig.Set("wait_for_callback", false);
172
122 TestScene scene = new SceneHelpers().SetupScene(); 173 TestScene scene = new SceneHelpers().SetupScene();
174 SceneHelpers.SetupSceneModules(scene, config, etm);
123 SceneHelpers.AddScenePresence(scene, spUuid); 175 SceneHelpers.AddScenePresence(scene, spUuid);
124 SceneHelpers.AddScenePresence(scene, spUuid); 176 SceneHelpers.AddScenePresence(scene, spUuid);
125 177
@@ -133,7 +185,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
133 } 185 }
134 186
135 [Test] 187 [Test]
136 public void TestCloseAgent() 188 public void TestCloseClient()
137 { 189 {
138 TestHelpers.InMethod(); 190 TestHelpers.InMethod();
139// TestHelpers.EnableLogging(); 191// TestHelpers.EnableLogging();
@@ -141,7 +193,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
141 TestScene scene = new SceneHelpers().SetupScene(); 193 TestScene scene = new SceneHelpers().SetupScene();
142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 194 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
143 195
144 scene.IncomingCloseAgent(sp.UUID, false); 196 scene.CloseAgent(sp.UUID, false);
145 197
146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 198 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
147 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); 199 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
@@ -187,7 +239,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
187 // *** This is the second stage, where the client established a child agent/scene presence using the 239 // *** This is the second stage, where the client established a child agent/scene presence using the
188 // circuit code given to the scene in stage 1 *** 240 // circuit code given to the scene in stage 1 ***
189 TestClient client = new TestClient(acd, scene); 241 TestClient client = new TestClient(acd, scene);
190 scene.AddNewClient(client, PresenceType.User); 242 scene.AddNewAgent(client, PresenceType.User);
191 243
192 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); 244 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null);
193 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 245 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
@@ -236,58 +288,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests
236// Assert.That(childPresence, Is.Not.Null); 288// Assert.That(childPresence, Is.Not.Null);
237// Assert.That(childPresence.IsChildAgent, Is.True); 289// Assert.That(childPresence.IsChildAgent, Is.True);
238 } 290 }
239
240// /// <summary>
241// /// Test adding a root agent to a scene. Doesn't yet actually complete crossing the agent into the scene.
242// /// </summary>
243// [Test]
244// public void T010_TestAddRootAgent()
245// {
246// TestHelpers.InMethod();
247//
248// string firstName = "testfirstname";
249//
250// AgentCircuitData agent = new AgentCircuitData();
251// agent.AgentID = agent1;
252// agent.firstname = firstName;
253// agent.lastname = "testlastname";
254// agent.SessionID = UUID.Random();
255// agent.SecureSessionID = UUID.Random();
256// agent.circuitcode = 123;
257// agent.BaseFolder = UUID.Zero;
258// agent.InventoryFolder = UUID.Zero;
259// agent.startpos = Vector3.Zero;
260// agent.CapsPath = GetRandomCapsObjectPath();
261// agent.ChildrenCapSeeds = new Dictionary<ulong, string>();
262// agent.child = true;
263//
264// scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID);
265//
266// string reason;
267// scene.NewUserConnection(agent, (uint)TeleportFlags.ViaLogin, out reason);
268// testclient = new TestClient(agent, scene);
269// scene.AddNewClient(testclient);
270//
271// ScenePresence presence = scene.GetScenePresence(agent1);
272//
273// Assert.That(presence, Is.Not.Null, "presence is null");
274// Assert.That(presence.Firstname, Is.EqualTo(firstName), "First name not same");
275// acd1 = agent;
276// }
277//
278// /// <summary>
279// /// Test removing an uncrossed root agent from a scene.
280// /// </summary>
281// [Test]
282// public void T011_TestRemoveRootAgent()
283// {
284// TestHelpers.InMethod();
285//
286// scene.RemoveClient(agent1);
287//
288// ScenePresence presence = scene.GetScenePresence(agent1);
289//
290// Assert.That(presence, Is.Null, "presence is not null");
291// }
292 } 291 }
293} \ No newline at end of file 292} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
new file mode 100644
index 0000000..9fa0a71
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.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.Generic;
30using System.Reflection;
31using System.Text;
32using System.Threading;
33using System.Timers;
34using Timer = System.Timers.Timer;
35using Nini.Config;
36using NUnit.Framework;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Communications;
40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.ClientStack.Linden;
43using OpenSim.Region.CoreModules.Framework;
44using OpenSim.Region.CoreModules.Framework.EntityTransfer;
45using OpenSim.Region.CoreModules.World.Serialiser;
46using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Framework.Interfaces;
49using OpenSim.Tests.Common;
50using OpenSim.Tests.Common.Mock;
51using GridRegion = OpenSim.Services.Interfaces.GridRegion;
52
53namespace OpenSim.Region.Framework.Scenes.Tests
54{
55 [TestFixture]
56 public class ScenePresenceCapabilityTests : OpenSimTestCase
57 {
58 [Test]
59 public void TestChildAgentSingleRegionCapabilities()
60 {
61 TestHelpers.InMethod();
62// TestHelpers.EnableLogging();
63
64 UUID spUuid = TestHelpers.ParseTail(0x1);
65
66 // XXX: This is not great since the use of statics will mean that this has to be manually cleaned up for
67 // any subsequent test.
68 // XXX: May replace with a mock IHttpServer later.
69 BaseHttpServer httpServer = new BaseHttpServer(99999);
70 MainServer.AddHttpServer(httpServer);
71 MainServer.Instance = httpServer;
72
73 CapabilitiesModule capsMod = new CapabilitiesModule();
74 TestScene scene = new SceneHelpers().SetupScene();
75 SceneHelpers.SetupSceneModules(scene, capsMod);
76
77 ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid);
78 //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null);
79
80 // TODO: Need to add tests for other ICapabiltiesModule methods.
81
82// scene.IncomingCloseAgent(sp.UUID, false);
83// //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
84 scene.CloseAgent(sp.UUID, false);
85// Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
86
87 // TODO: Need to add tests for other ICapabiltiesModule methods.
88 }
89 }
90}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
index 8775949..b806a97 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
@@ -38,6 +38,7 @@ using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.CoreModules.Framework; 38using OpenSim.Region.CoreModules.Framework;
39using OpenSim.Region.CoreModules.Framework.EntityTransfer; 39using OpenSim.Region.CoreModules.Framework.EntityTransfer;
40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
41using OpenSim.Region.CoreModules.World.Permissions;
41using OpenSim.Tests.Common; 42using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock; 43using OpenSim.Tests.Common.Mock;
43 44
@@ -95,11 +96,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
95 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); 96 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
96 97
97 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 98 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
98 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 99 TestClient tc = new TestClient(acd, sceneA);
99 List<TestClient> destinationTestClients = new List<TestClient>(); 100 List<TestClient> destinationTestClients = new List<TestClient>();
100 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 101 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
101 102
102 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 103 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
103 originalSp.AbsolutePosition = new Vector3(128, 32, 10); 104 originalSp.AbsolutePosition = new Vector3(128, 32, 10);
104 105
105// originalSp.Flying = true; 106// originalSp.Flying = true;
@@ -112,6 +113,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
112 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero); 113 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
113 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2))); 114 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
114 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; 115 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
116 moveArgs.SessionID = acd.SessionID;
115 117
116 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs); 118 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
117 119
@@ -158,5 +160,90 @@ namespace OpenSim.Region.Framework.Scenes.Tests
158 Assert.That(agentMovementCompleteReceived, Is.EqualTo(1)); 160 Assert.That(agentMovementCompleteReceived, Is.EqualTo(1));
159 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False); 161 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False);
160 } 162 }
163
164 /// <summary>
165 /// Test a cross attempt where the user can see into the neighbour but does not have permission to become
166 /// root there.
167 /// </summary>
168 [Test]
169 public void TestCrossOnSameSimulatorNoRootDestPerm()
170 {
171 TestHelpers.InMethod();
172// TestHelpers.EnableLogging();
173
174 UUID userId = TestHelpers.ParseTail(0x1);
175
176 EntityTransferModule etmA = new EntityTransferModule();
177 EntityTransferModule etmB = new EntityTransferModule();
178 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
179
180 IConfigSource config = new IniConfigSource();
181 IConfig modulesConfig = config.AddConfig("Modules");
182 modulesConfig.Set("EntityTransferModule", etmA.Name);
183 modulesConfig.Set("SimulationServices", lscm.Name);
184
185 SceneHelpers sh = new SceneHelpers();
186 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
187 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
188
189 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
190 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
191
192 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
193 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
194 // IsAdministrator if no permissions module is present is true.
195// SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB);
196
197 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
198 TestClient tc = new TestClient(acd, sceneA);
199 List<TestClient> destinationTestClients = new List<TestClient>();
200 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
201
202 // Make sure sceneB will not accept this avatar.
203 sceneB.RegionInfo.EstateSettings.PublicAccess = false;
204
205 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
206 originalSp.AbsolutePosition = new Vector3(128, 32, 10);
207
208 AgentUpdateArgs moveArgs = new AgentUpdateArgs();
209 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
210 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
211 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
212 moveArgs.SessionID = acd.SessionID;
213
214 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
215
216 sceneA.Update(1);
217
218// Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition);
219
220 // FIXME: This is a sufficient number of updates to for the presence to reach the northern border.
221 // But really we want to do this in a more robust way.
222 for (int i = 0; i < 100; i++)
223 {
224 sceneA.Update(1);
225// Console.WriteLine("Pos {0}", originalSp.AbsolutePosition);
226 }
227
228 // sceneA agent should still be root
229 ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID);
230 Assert.That(spAfterCrossSceneA.IsChildAgent, Is.False);
231
232 ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID);
233
234 // sceneB agent should also still be root
235 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
236
237 // sceneB should ignore unauthorized attempt to upgrade agent to root
238 TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient);
239
240 int agentMovementCompleteReceived = 0;
241 sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++;
242
243 sceneBTc.CompleteMovement();
244
245 Assert.That(agentMovementCompleteReceived, Is.EqualTo(0));
246 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
247 }
161 } 248 }
162} \ No newline at end of file 249}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index acaeb90..0911f00 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -111,15 +111,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
111 111
112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; 112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
113 113
114 // We need to preserve this here because phys actor is removed by the sit.
115 Vector3 spPhysActorSize = m_sp.PhysicsActor.Size;
114 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); 116 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
115 117
116 // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the
117 // default avatar.
118 // Curiously, Vector3.ToString() will not display the last two places of the float. For example,
119 // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337>
120 Assert.That( 118 Assert.That(
121 m_sp.AbsolutePosition, 119 m_sp.AbsolutePosition,
122 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, 0.845499337f))); 120 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, spPhysActorSize.Z / 2)));
123 121
124 m_sp.StandUp(); 122 m_sp.StandUp();
125 123
@@ -147,9 +145,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
147 145
148 Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID)); 146 Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID));
149 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); 147 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
150 Assert.That( 148// Assert.That(
151 m_sp.AbsolutePosition, 149// m_sp.AbsolutePosition,
152 Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); 150// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
153 Assert.That(m_sp.PhysicsActor, Is.Null); 151 Assert.That(m_sp.PhysicsActor, Is.Null);
154 152
155 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); 153 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index 8d94d29..fff542b 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net; 31using System.Net;
32using System.Text; 32using System.Text;
33using System.Threading;
33using Nini.Config; 34using Nini.Config;
34using NUnit.Framework; 35using NUnit.Framework;
35using OpenMetaverse; 36using OpenMetaverse;
@@ -107,7 +108,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
107 } 108 }
108 109
109 [Test] 110 [Test]
110 public void TestSameSimulatorIsolatedRegions() 111 public void TestSameSimulatorIsolatedRegionsV1()
111 { 112 {
112 TestHelpers.InMethod(); 113 TestHelpers.InMethod();
113// TestHelpers.EnableLogging(); 114// TestHelpers.EnableLogging();
@@ -136,14 +137,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests
136 SceneHelpers.SetupSceneModules(sceneB, config, etmB); 137 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
137 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 138 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
138 139
140 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
141 lscm.ServiceVersion = "SIMULATION/0.1";
142
139 Vector3 teleportPosition = new Vector3(10, 11, 12); 143 Vector3 teleportPosition = new Vector3(10, 11, 12);
140 Vector3 teleportLookAt = new Vector3(20, 21, 22); 144 Vector3 teleportLookAt = new Vector3(20, 21, 22);
141 145
142 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 146 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
143 sp.AbsolutePosition = new Vector3(30, 31, 32); 147 sp.AbsolutePosition = new Vector3(30, 31, 32);
144 148
145 List<TestClient> destinationTestClients = new List<TestClient>(); 149 List<TestClient> destinationTestClients = new List<TestClient>();
146 EntityTransferHelpers.SetUpInformClientOfNeighbour((TestClient)sp.ControllingClient, destinationTestClients); 150 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(
151 (TestClient)sp.ControllingClient, destinationTestClients);
147 152
148 sceneA.RequestTeleportLocation( 153 sceneA.RequestTeleportLocation(
149 sp.ControllingClient, 154 sp.ControllingClient,
@@ -176,6 +181,67 @@ namespace OpenSim.Region.Framework.Scenes.Tests
176// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); 181// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
177 } 182 }
178 183
184 [Test]
185 public void TestSameSimulatorIsolatedRegionsV2()
186 {
187 TestHelpers.InMethod();
188// TestHelpers.EnableLogging();
189
190 UUID userId = TestHelpers.ParseTail(0x1);
191
192 EntityTransferModule etmA = new EntityTransferModule();
193 EntityTransferModule etmB = new EntityTransferModule();
194 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
195
196 IConfigSource config = new IniConfigSource();
197 IConfig modulesConfig = config.AddConfig("Modules");
198 modulesConfig.Set("EntityTransferModule", etmA.Name);
199 modulesConfig.Set("SimulationServices", lscm.Name);
200
201 SceneHelpers sh = new SceneHelpers();
202 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
203 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000);
204
205 SceneHelpers.SetupSceneModules(sceneA, config, etmA);
206 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
207 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
208
209 Vector3 teleportPosition = new Vector3(10, 11, 12);
210 Vector3 teleportLookAt = new Vector3(20, 21, 22);
211
212 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
213 sp.AbsolutePosition = new Vector3(30, 31, 32);
214
215 List<TestClient> destinationTestClients = new List<TestClient>();
216 EntityTransferHelpers.SetupSendRegionTeleportTriggersDestinationClientCreateAndCompleteMovement(
217 (TestClient)sp.ControllingClient, destinationTestClients);
218
219 sceneA.RequestTeleportLocation(
220 sp.ControllingClient,
221 sceneB.RegionInfo.RegionHandle,
222 teleportPosition,
223 teleportLookAt,
224 (uint)TeleportFlags.ViaLocation);
225
226 Assert.That(sceneA.GetScenePresence(userId), Is.Null);
227
228 ScenePresence sceneBSp = sceneB.GetScenePresence(userId);
229 Assert.That(sceneBSp, Is.Not.Null);
230 Assert.That(sceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName));
231 Assert.That(sceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition));
232
233 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0));
234 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0));
235 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1));
236 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
237
238 // TODO: Add assertions to check correct circuit details in both scenes.
239
240 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
241 // position instead).
242// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
243 }
244
179 /// <summary> 245 /// <summary>
180 /// Test teleport procedures when the target simulator returns false when queried about access. 246 /// Test teleport procedures when the target simulator returns false when queried about access.
181 /// </summary> 247 /// </summary>
@@ -224,7 +290,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
224 Vector3 teleportPosition = new Vector3(10, 11, 12); 290 Vector3 teleportPosition = new Vector3(10, 11, 12);
225 Vector3 teleportLookAt = new Vector3(20, 21, 22); 291 Vector3 teleportLookAt = new Vector3(20, 21, 22);
226 292
227 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 293 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
228 sp.AbsolutePosition = preTeleportPosition; 294 sp.AbsolutePosition = preTeleportPosition;
229 295
230 // Make sceneB return false on query access 296 // Make sceneB return false on query access
@@ -300,7 +366,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
300 Vector3 teleportPosition = new Vector3(10, 11, 12); 366 Vector3 teleportPosition = new Vector3(10, 11, 12);
301 Vector3 teleportLookAt = new Vector3(20, 21, 22); 367 Vector3 teleportLookAt = new Vector3(20, 21, 22);
302 368
303 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 369 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
304 sp.AbsolutePosition = preTeleportPosition; 370 sp.AbsolutePosition = preTeleportPosition;
305 371
306 // Make sceneB refuse CreateAgent 372 // Make sceneB refuse CreateAgent
@@ -389,7 +455,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
389 Vector3 teleportPosition = new Vector3(10, 11, 12); 455 Vector3 teleportPosition = new Vector3(10, 11, 12);
390 Vector3 teleportLookAt = new Vector3(20, 21, 22); 456 Vector3 teleportLookAt = new Vector3(20, 21, 22);
391 457
392 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 458 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
393 sp.AbsolutePosition = preTeleportPosition; 459 sp.AbsolutePosition = preTeleportPosition;
394 460
395 sceneA.RequestTeleportLocation( 461 sceneA.RequestTeleportLocation(
@@ -425,10 +491,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
425 } 491 }
426 492
427 [Test] 493 [Test]
428 public void TestSameSimulatorNeighbouringRegions() 494 public void TestSameSimulatorNeighbouringRegionsV1()
429 { 495 {
430 TestHelpers.InMethod(); 496 TestHelpers.InMethod();
431 TestHelpers.EnableLogging(); 497// TestHelpers.EnableLogging();
432 498
433 UUID userId = TestHelpers.ParseTail(0x1); 499 UUID userId = TestHelpers.ParseTail(0x1);
434 500
@@ -454,15 +520,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests
454 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); 520 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
455 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); 521 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
456 522
523 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
524 lscm.ServiceVersion = "SIMULATION/0.1";
525
457 Vector3 teleportPosition = new Vector3(10, 11, 12); 526 Vector3 teleportPosition = new Vector3(10, 11, 12);
458 Vector3 teleportLookAt = new Vector3(20, 21, 22); 527 Vector3 teleportLookAt = new Vector3(20, 21, 22);
459 528
460 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 529 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
461 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 530 TestClient tc = new TestClient(acd, sceneA);
462 List<TestClient> destinationTestClients = new List<TestClient>(); 531 List<TestClient> destinationTestClients = new List<TestClient>();
463 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 532 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
464 533
465 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 534 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
466 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32); 535 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32);
467 536
468 Assert.That(beforeSceneASp, Is.Not.Null); 537 Assert.That(beforeSceneASp, Is.Not.Null);
@@ -506,5 +575,89 @@ namespace OpenSim.Region.Framework.Scenes.Tests
506 575
507// TestHelpers.DisableLogging(); 576// TestHelpers.DisableLogging();
508 } 577 }
578
579 [Test]
580 public void TestSameSimulatorNeighbouringRegionsV2()
581 {
582 TestHelpers.InMethod();
583// TestHelpers.EnableLogging();
584
585 UUID userId = TestHelpers.ParseTail(0x1);
586
587 EntityTransferModule etmA = new EntityTransferModule();
588 EntityTransferModule etmB = new EntityTransferModule();
589 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
590
591 IConfigSource config = new IniConfigSource();
592 IConfig modulesConfig = config.AddConfig("Modules");
593 modulesConfig.Set("EntityTransferModule", etmA.Name);
594 modulesConfig.Set("SimulationServices", lscm.Name);
595
596 SceneHelpers sh = new SceneHelpers();
597 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
598 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
599
600 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
601 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
602 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
603
604 Vector3 teleportPosition = new Vector3(10, 11, 12);
605 Vector3 teleportLookAt = new Vector3(20, 21, 22);
606
607 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
608 TestClient tc = new TestClient(acd, sceneA);
609 List<TestClient> destinationTestClients = new List<TestClient>();
610 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
611
612 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
613 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32);
614
615 Assert.That(beforeSceneASp, Is.Not.Null);
616 Assert.That(beforeSceneASp.IsChildAgent, Is.False);
617
618 ScenePresence beforeSceneBSp = sceneB.GetScenePresence(userId);
619 Assert.That(beforeSceneBSp, Is.Not.Null);
620 Assert.That(beforeSceneBSp.IsChildAgent, Is.True);
621
622 // Here, we need to make clientA's receipt of SendRegionTeleport trigger clientB's CompleteMovement(). This
623 // is to operate the teleport V2 mechanism where the EntityTransferModule will first request the client to
624 // CompleteMovement to the region and then call UpdateAgent to the destination region to confirm the receipt
625 // Both these operations will occur on different threads and will wait for each other.
626 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1
627 // test protocol, where we are trying to avoid unpredictable async operations in regression tests.
628 tc.OnTestClientSendRegionTeleport
629 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL)
630 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null);
631
632 sceneA.RequestTeleportLocation(
633 beforeSceneASp.ControllingClient,
634 sceneB.RegionInfo.RegionHandle,
635 teleportPosition,
636 teleportLookAt,
637 (uint)TeleportFlags.ViaLocation);
638
639 ScenePresence afterSceneASp = sceneA.GetScenePresence(userId);
640 Assert.That(afterSceneASp, Is.Not.Null);
641 Assert.That(afterSceneASp.IsChildAgent, Is.True);
642
643 ScenePresence afterSceneBSp = sceneB.GetScenePresence(userId);
644 Assert.That(afterSceneBSp, Is.Not.Null);
645 Assert.That(afterSceneBSp.IsChildAgent, Is.False);
646 Assert.That(afterSceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName));
647 Assert.That(afterSceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition));
648
649 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0));
650 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(1));
651 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1));
652 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
653
654 // TODO: Add assertions to check correct circuit details in both scenes.
655
656 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
657 // position instead).
658// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
659
660// TestHelpers.DisableLogging();
661 }
509 } 662 }
510} 663}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs
new file mode 100644
index 0000000..1667002
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.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 System.Reflection;
31using NUnit.Framework;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock;
38
39namespace OpenSim.Region.Framework.Scenes.Tests
40{
41 [TestFixture]
42 public class SceneStatisticsTests : OpenSimTestCase
43 {
44 private TestScene m_scene;
45
46 [SetUp]
47 public void Init()
48 {
49 m_scene = new SceneHelpers().SetupScene();
50 }
51
52 [Test]
53 public void TestAddRemovePhysicalLinkset()
54 {
55 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(0));
56
57 UUID ownerId = TestHelpers.ParseTail(0x1);
58 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10);
59 so1.ScriptSetPhysicsStatus(true);
60 m_scene.AddSceneObject(so1);
61
62 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3));
63 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3));
64
65 m_scene.DeleteSceneObject(so1, false);
66
67 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(0));
68 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(0));
69 }
70 }
71} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
new file mode 100644
index 0000000..9a97acc
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
@@ -0,0 +1,119 @@
1/*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions are met:
4 * * Redistributions of source code must retain the above copyright
5 * notice, this list of conditions and the following disclaimer.
6 * * Redistributions in binary form must reproduce the above copyright
7 * notice, this list of conditions and the following disclaimer in the
8 * documentation and/or other materials provided with the distribution.
9 * * Neither the name of the OpenSimulator Project nor the
10 * names of its contributors may be used to endorse or promote products
11 * derived from this software without specific prior written permission.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25using System;
26using Nini.Config;
27using NUnit.Framework;
28using OpenMetaverse;
29using OpenSim.Framework;
30using OpenSim.Region.CoreModules.World.Estate;
31using OpenSim.Region.Framework.Scenes;
32using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Services.Interfaces;
34using OpenSim.Tests.Common;
35using OpenSim.Tests.Common.Mock;
36
37namespace OpenSim.Region.Framework.Scenes.Tests
38{
39 /// <summary>
40 /// Scene telehub tests
41 /// </summary>
42 /// <remarks>
43 /// TODO: Tests which run through normal functionality. Currently, the only test is one that checks behaviour
44 /// in the case of an error condition
45 /// </remarks>
46 [TestFixture]
47 public class SceneTelehubTests : OpenSimTestCase
48 {
49 /// <summary>
50 /// Test for desired behaviour when a telehub has no spawn points
51 /// </summary>
52 [Test]
53 public void TestNoTelehubSpawnPoints()
54 {
55 TestHelpers.InMethod();
56// TestHelpers.EnableLogging();
57
58 EstateManagementModule emm = new EstateManagementModule();
59
60 SceneHelpers sh = new SceneHelpers();
61 Scene scene = sh.SetupScene();
62 SceneHelpers.SetupSceneModules(scene, emm);
63
64 UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
65
66 SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
67
68 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
69 scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
70
71 // Must still be possible to successfully log in
72 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
73
74 UserAccount ua
75 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
76
77 SceneHelpers.AddScenePresence(scene, ua);
78
79 Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
80 }
81
82 /// <summary>
83 /// Test for desired behaviour when the scene object nominated as a telehub object does not exist.
84 /// </summary>
85 [Test]
86 public void TestNoTelehubSceneObject()
87 {
88 TestHelpers.InMethod();
89// TestHelpers.EnableLogging();
90
91 EstateManagementModule emm = new EstateManagementModule();
92
93 SceneHelpers sh = new SceneHelpers();
94 Scene scene = sh.SetupScene();
95 SceneHelpers.SetupSceneModules(scene, emm);
96
97 UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
98
99 SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
100 SceneObjectGroup spawnPointSo = SceneHelpers.AddSceneObject(scene, "spawnpointObject", telehubSceneObjectOwner);
101
102 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
103 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "spawnpoint add", spawnPointSo.LocalId);
104 scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
105
106 scene.DeleteSceneObject(telehubSo, false);
107
108 // Must still be possible to successfully log in
109 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
110
111 UserAccount ua
112 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
113
114 SceneHelpers.AddScenePresence(scene, ua);
115
116 Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
117 }
118 }
119} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index dd27294..1e59e3f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -62,8 +62,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); 62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero);
63 m_assetService.Store(corruptAsset); 63 m_assetService.Store(corruptAsset);
64 64
65 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 65 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, AssetType.Object, foundAssetUuids); 66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
67 67
68 // We count the uuid as gathered even if the asset itself is corrupt. 68 // We count the uuid as gathered even if the asset itself is corrupt.
69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -78,9 +78,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
78 TestHelpers.InMethod(); 78 TestHelpers.InMethod();
79 79
80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); 80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
81 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 81 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
82 82
83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, AssetType.Object, foundAssetUuids); 83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
84 84
85 // We count the uuid as gathered even if the asset itself is missing. 85 // We count the uuid as gathered even if the asset itself is missing.
86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -103,8 +103,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString()); 103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString());
104 m_assetService.Store(ncAsset); 104 m_assetService.Store(ncAsset);
105 105
106 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 106 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
107 m_uuidGatherer.GatherAssetUuids(ncAssetId, AssetType.Notecard, foundAssetUuids); 107 m_uuidGatherer.GatherAssetUuids(ncAssetId, (sbyte)AssetType.Notecard, foundAssetUuids);
108 108
109 // We count the uuid as gathered even if the asset itself is corrupt. 109 // We count the uuid as gathered even if the asset itself is corrupt.
110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2)); 110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2));
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index b09ae39..67655d6 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -34,9 +34,11 @@ using System.Threading;
34using log4net; 34using log4net;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenMetaverse.Assets; 36using OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Region.Framework.Scenes.Serialization; 39using OpenSim.Region.Framework.Scenes.Serialization;
39using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
40 42
41namespace OpenSim.Region.Framework.Scenes 43namespace OpenSim.Region.Framework.Scenes
42{ 44{
@@ -82,29 +84,33 @@ namespace OpenSim.Region.Framework.Scenes
82 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> 84 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
83 /// <param name="assetType">The type of the asset for the uuid given</param> 85 /// <param name="assetType">The type of the asset for the uuid given</param>
84 /// <param name="assetUuids">The assets gathered</param> 86 /// <param name="assetUuids">The assets gathered</param>
85 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 87 public void GatherAssetUuids(UUID assetUuid, sbyte assetType, IDictionary<UUID, sbyte> assetUuids)
86 { 88 {
87 try 89 try
88 { 90 {
89 assetUuids[assetUuid] = assetType; 91 assetUuids[assetUuid] = assetType;
90 92
91 if (AssetType.Bodypart == assetType || AssetType.Clothing == assetType) 93 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
92 { 94 {
93 GetWearableAssetUuids(assetUuid, assetUuids); 95 GetWearableAssetUuids(assetUuid, assetUuids);
94 } 96 }
95 else if (AssetType.Gesture == assetType) 97 else if ((sbyte)AssetType.Gesture == assetType)
96 { 98 {
97 GetGestureAssetUuids(assetUuid, assetUuids); 99 GetGestureAssetUuids(assetUuid, assetUuids);
98 } 100 }
99 else if (AssetType.Notecard == assetType) 101 else if ((sbyte)AssetType.Notecard == assetType)
100 { 102 {
101 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 103 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
102 } 104 }
103 else if (AssetType.LSLText == assetType) 105 else if ((sbyte)AssetType.LSLText == assetType)
104 { 106 {
105 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 107 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
106 } 108 }
107 else if (AssetType.Object == assetType) 109 else if ((sbyte)OpenSimAssetType.Material == assetType)
110 {
111 GetMaterialAssetUuids(assetUuid, assetUuids);
112 }
113 else if ((sbyte)AssetType.Object == assetType)
108 { 114 {
109 GetSceneObjectAssetUuids(assetUuid, assetUuids); 115 GetSceneObjectAssetUuids(assetUuid, assetUuids);
110 } 116 }
@@ -131,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. 137 /// 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. 138 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown.
133 /// </param> 139 /// </param>
134 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) 140 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids)
135 { 141 {
136// m_log.DebugFormat( 142// m_log.DebugFormat(
137// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); 143// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
@@ -151,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
151 { 157 {
152 // Get the prim's default texture. This will be used for faces which don't have their own texture 158 // Get the prim's default texture. This will be used for faces which don't have their own texture
153 if (textureEntry.DefaultTexture != null) 159 if (textureEntry.DefaultTexture != null)
154 assetUuids[textureEntry.DefaultTexture.TextureID] = AssetType.Texture; 160 assetUuids[textureEntry.DefaultTexture.TextureID] = (sbyte)AssetType.Texture;
155 161
156 if (textureEntry.FaceTextures != null) 162 if (textureEntry.FaceTextures != null)
157 { 163 {
@@ -159,15 +165,37 @@ namespace OpenSim.Region.Framework.Scenes
159 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) 165 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
160 { 166 {
161 if (texture != null) 167 if (texture != null)
162 assetUuids[texture.TextureID] = AssetType.Texture; 168 assetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
163 } 169 }
164 } 170 }
165 } 171 }
166 172
167 // If the prim is a sculpt then preserve this information too 173 // If the prim is a sculpt then preserve this information too
168 if (part.Shape.SculptTexture != UUID.Zero) 174 if (part.Shape.SculptTexture != UUID.Zero)
169 assetUuids[part.Shape.SculptTexture] = AssetType.Texture; 175 assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
170 176
177 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
178 assetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
179
180 if (part.CollisionSound != UUID.Zero)
181 assetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
182
183 if (part.ParticleSystem.Length > 0)
184 {
185 try
186 {
187 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
188 if (ps.Texture != UUID.Zero)
189 assetUuids[ps.Texture] = (sbyte)AssetType.Texture;
190 }
191 catch (Exception e)
192 {
193 m_log.WarnFormat(
194 "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.",
195 part.Name, part.UUID, sceneObject.Name, sceneObject.UUID);
196 }
197 }
198
171 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 199 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
172 200
173 // Now analyze this prim's inventory items to preserve all the uuids that they reference 201 // Now analyze this prim's inventory items to preserve all the uuids that they reference
@@ -178,8 +206,18 @@ namespace OpenSim.Region.Framework.Scenes
178// tii.Name, tii.Type, part.Name, part.UUID); 206// tii.Name, tii.Type, part.Name, part.UUID);
179 207
180 if (!assetUuids.ContainsKey(tii.AssetID)) 208 if (!assetUuids.ContainsKey(tii.AssetID))
181 GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); 209 GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids);
182 } 210 }
211
212 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
213 // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and
214 // inventory transfer. There needs to be a way for a module to register a method without assuming a
215 // Scene.EventManager is present.
216// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
217
218
219 // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
220 GatherMaterialsUuids(part, assetUuids);
183 } 221 }
184 catch (Exception e) 222 catch (Exception e)
185 { 223 {
@@ -190,7 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
190 } 228 }
191 } 229 }
192 } 230 }
193 231
194// /// <summary> 232// /// <summary>
195// /// The callback made when we request the asset for an object from the asset service. 233// /// The callback made when we request the asset for an object from the asset service.
196// /// </summary> 234// /// </summary>
@@ -205,6 +243,75 @@ namespace OpenSim.Region.Framework.Scenes
205// } 243// }
206 244
207 /// <summary> 245 /// <summary>
246 /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
247 /// stored in legacy format in part.DynAttrs
248 /// </summary>
249 /// <param name="part"></param>
250 /// <param name="assetUuids"></param>
251 //public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
252 public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, sbyte> assetUuids)
253 {
254 // scan thru the dynAttrs map of this part for any textures used as materials
255 OSD osdMaterials = null;
256
257 lock (part.DynAttrs)
258 {
259 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
260 {
261 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
262
263 if (materialsStore == null)
264 return;
265
266 materialsStore.TryGetValue("Materials", out osdMaterials);
267 }
268
269 if (osdMaterials != null)
270 {
271 //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
272
273 if (osdMaterials is OSDArray)
274 {
275 OSDArray matsArr = osdMaterials as OSDArray;
276 foreach (OSDMap matMap in matsArr)
277 {
278 try
279 {
280 if (matMap.ContainsKey("Material"))
281 {
282 OSDMap mat = matMap["Material"] as OSDMap;
283 if (mat.ContainsKey("NormMap"))
284 {
285 UUID normalMapId = mat["NormMap"].AsUUID();
286 if (normalMapId != UUID.Zero)
287 {
288 assetUuids[normalMapId] = (sbyte)AssetType.Texture;
289 //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
290 }
291 }
292 if (mat.ContainsKey("SpecMap"))
293 {
294 UUID specularMapId = mat["SpecMap"].AsUUID();
295 if (specularMapId != UUID.Zero)
296 {
297 assetUuids[specularMapId] = (sbyte)AssetType.Texture;
298 //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
299 }
300 }
301 }
302
303 }
304 catch (Exception e)
305 {
306 m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message);
307 }
308 }
309 }
310 }
311 }
312 }
313
314 /// <summary>
208 /// Get an asset synchronously, potentially using an asynchronous callback. If the 315 /// Get an asset synchronously, potentially using an asynchronous callback. If the
209 /// asynchronous callback is used, we will wait for it to complete. 316 /// asynchronous callback is used, we will wait for it to complete.
210 /// </summary> 317 /// </summary>
@@ -242,7 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
242 /// </summary> 349 /// </summary>
243 /// <param name="scriptUuid"></param> 350 /// <param name="scriptUuid"></param>
244 /// <param name="assetUuids">Dictionary in which to record the references</param> 351 /// <param name="assetUuids">Dictionary in which to record the references</param>
245 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, AssetType> assetUuids) 352 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, sbyte> assetUuids)
246 { 353 {
247// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); 354// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId);
248 355
@@ -262,7 +369,7 @@ namespace OpenSim.Region.Framework.Scenes
262 369
263 // Embedded asset references (if not false positives) could be for many types of asset, so we will 370 // Embedded asset references (if not false positives) could be for many types of asset, so we will
264 // label these as unknown. 371 // label these as unknown.
265 assetUuids[uuid] = AssetType.Unknown; 372 assetUuids[uuid] = (sbyte)AssetType.Unknown;
266 } 373 }
267 } 374 }
268 } 375 }
@@ -272,7 +379,7 @@ namespace OpenSim.Region.Framework.Scenes
272 /// </summary> 379 /// </summary>
273 /// <param name="wearableAssetUuid"></param> 380 /// <param name="wearableAssetUuid"></param>
274 /// <param name="assetUuids">Dictionary in which to record the references</param> 381 /// <param name="assetUuids">Dictionary in which to record the references</param>
275 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, AssetType> assetUuids) 382 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, sbyte> assetUuids)
276 { 383 {
277 AssetBase assetBase = GetAsset(wearableAssetUuid); 384 AssetBase assetBase = GetAsset(wearableAssetUuid);
278 385
@@ -287,7 +394,7 @@ namespace OpenSim.Region.Framework.Scenes
287 394
288 foreach (UUID uuid in wearableAsset.Textures.Values) 395 foreach (UUID uuid in wearableAsset.Textures.Values)
289 { 396 {
290 assetUuids[uuid] = AssetType.Texture; 397 assetUuids[uuid] = (sbyte)AssetType.Texture;
291 } 398 }
292 } 399 }
293 } 400 }
@@ -299,7 +406,7 @@ namespace OpenSim.Region.Framework.Scenes
299 /// </summary> 406 /// </summary>
300 /// <param name="sceneObject"></param> 407 /// <param name="sceneObject"></param>
301 /// <param name="assetUuids"></param> 408 /// <param name="assetUuids"></param>
302 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, AssetType> assetUuids) 409 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, sbyte> assetUuids)
303 { 410 {
304 AssetBase objectAsset = GetAsset(sceneObjectUuid); 411 AssetBase objectAsset = GetAsset(sceneObjectUuid);
305 412
@@ -328,7 +435,7 @@ namespace OpenSim.Region.Framework.Scenes
328 /// </summary> 435 /// </summary>
329 /// <param name="gestureUuid"></param> 436 /// <param name="gestureUuid"></param>
330 /// <param name="assetUuids"></param> 437 /// <param name="assetUuids"></param>
331 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, AssetType> assetUuids) 438 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, sbyte> assetUuids)
332 { 439 {
333 AssetBase assetBase = GetAsset(gestureUuid); 440 AssetBase assetBase = GetAsset(gestureUuid);
334 if (null == assetBase) 441 if (null == assetBase)
@@ -362,9 +469,29 @@ namespace OpenSim.Region.Framework.Scenes
362 // If it can be parsed as a UUID, it is an asset ID 469 // If it can be parsed as a UUID, it is an asset ID
363 UUID uuid; 470 UUID uuid;
364 if (UUID.TryParse(id, out uuid)) 471 if (UUID.TryParse(id, out uuid))
365 assetUuids[uuid] = AssetType.Animation; 472 assetUuids[uuid] = (sbyte)AssetType.Animation;
366 } 473 }
367 } 474 }
475
476 /// <summary>
477 /// Get the asset uuid's referenced in a material.
478 /// </summary>
479 private void GetMaterialAssetUuids(UUID materialUuid, IDictionary<UUID, sbyte> assetUuids)
480 {
481 AssetBase assetBase = GetAsset(materialUuid);
482 if (null == assetBase)
483 return;
484
485 OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(assetBase.Data);
486
487 UUID normMap = mat["NormMap"].AsUUID();
488 if (normMap != UUID.Zero)
489 assetUuids[normMap] = (sbyte)AssetType.Texture;
490
491 UUID specMap = mat["SpecMap"].AsUUID();
492 if (specMap != UUID.Zero)
493 assetUuids[specMap] = (sbyte)AssetType.Texture;
494 }
368 } 495 }
369 496
370 public class HGUuidGatherer : UuidGatherer 497 public class HGUuidGatherer : UuidGatherer
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index dd72cfb..373ed41 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -660,6 +660,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
660 public event BakeTerrain OnBakeTerrain; 660 public event BakeTerrain OnBakeTerrain;
661 public event EstateChangeInfo OnEstateChangeInfo; 661 public event EstateChangeInfo OnEstateChangeInfo;
662 public event EstateManageTelehub OnEstateManageTelehub; 662 public event EstateManageTelehub OnEstateManageTelehub;
663 public event CachedTextureRequest OnCachedTextureRequest;
663 public event SetAppearance OnSetAppearance; 664 public event SetAppearance OnSetAppearance;
664 public event AvatarNowWearing OnAvatarNowWearing; 665 public event AvatarNowWearing OnAvatarNowWearing;
665 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; 666 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
@@ -687,6 +688,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
687 public event Action<IClientAPI, bool> OnCompleteMovementToRegion; 688 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
688 public event UpdateAgent OnPreAgentUpdate; 689 public event UpdateAgent OnPreAgentUpdate;
689 public event UpdateAgent OnAgentUpdate; 690 public event UpdateAgent OnAgentUpdate;
691 public event UpdateAgent OnAgentCameraUpdate;
690 public event AgentRequestSit OnAgentRequestSit; 692 public event AgentRequestSit OnAgentRequestSit;
691 public event AgentSit OnAgentSit; 693 public event AgentSit OnAgentSit;
692 public event AvatarPickerRequest OnAvatarPickerRequest; 694 public event AvatarPickerRequest OnAvatarPickerRequest;
@@ -906,7 +908,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
906 908
907 public void Start() 909 public void Start()
908 { 910 {
909 m_scene.AddNewClient(this, PresenceType.User); 911 m_scene.AddNewAgent(this, PresenceType.User);
910 912
911 // Mimicking LLClientView which gets always set appearance from client. 913 // Mimicking LLClientView which gets always set appearance from client.
912 AvatarAppearance appearance; 914 AvatarAppearance appearance;
@@ -943,13 +945,18 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
943 { 945 {
944 946
945 } 947 }
948
949 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
950 {
946 951
952 }
953
947 public void SendStartPingCheck(byte seq) 954 public void SendStartPingCheck(byte seq)
948 { 955 {
949 956
950 } 957 }
951 958
952 public void SendKillObject(ulong regionHandle, List<uint> localID) 959 public void SendKillObject(List<uint> localID)
953 { 960 {
954 961
955 } 962 }
@@ -1681,7 +1688,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1681 { 1688 {
1682 } 1689 }
1683 1690
1684 public void StopFlying(ISceneEntity presence) 1691 public void SendAgentTerseUpdate(ISceneEntity presence)
1685 { 1692 {
1686 } 1693 }
1687 1694
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
index 992f38e..ec18db0 100644
--- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
30using System.Reflection; 31using System.Reflection;
31using System.Text; 32using System.Text;
32using log4net; 33using log4net;
@@ -51,7 +52,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LindenUDPInfoModule")] 52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LindenUDPInfoModule")]
52 public class LindenUDPInfoModule : ISharedRegionModule 53 public class LindenUDPInfoModule : ISharedRegionModule
53 { 54 {
54// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 56
56 protected Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>(); 57 protected Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
57 58
@@ -130,6 +131,15 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
130 "Go on/off emergency monitoring mode", 131 "Go on/off emergency monitoring mode",
131 "Go on/off emergency monitoring mode", 132 "Go on/off emergency monitoring mode",
132 HandleEmergencyMonitoring); 133 HandleEmergencyMonitoring);
134
135 scene.AddCommand(
136 "Comms", this, "show client stats",
137 "show client stats [first_name last_name]",
138 "Show client request stats",
139 "Without the 'first_name last_name' option, all clients are shown."
140 + " With the 'first_name last_name' option only a specific client is shown.",
141 (mod, cmd) => MainConsole.Instance.Output(HandleClientStatsReport(cmd)));
142
133 } 143 }
134 144
135 public void RemoveRegion(Scene scene) 145 public void RemoveRegion(Scene scene)
@@ -294,7 +304,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
294 private string GetImageQueuesReport(string[] showParams) 304 private string GetImageQueuesReport(string[] showParams)
295 { 305 {
296 if (showParams.Length < 5 || showParams.Length > 6) 306 if (showParams.Length < 5 || showParams.Length > 6)
297 return "Usage: image queues show <first-name> <last-name> [full]"; 307 return "Usage: show image queues <first-name> <last-name> [full]";
298 308
299 string firstName = showParams[3]; 309 string firstName = showParams[3];
300 string lastName = showParams[4]; 310 string lastName = showParams[4];
@@ -385,7 +395,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
385 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); 395 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
386 396
387 report.AppendFormat( 397 report.AppendFormat(
388 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", 398 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7}\n",
389 "Since", 399 "Since",
390 "Pkts", 400 "Pkts",
391 "Pkts", 401 "Pkts",
@@ -397,12 +407,11 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
397 "Q Pkts", 407 "Q Pkts",
398 "Q Pkts", 408 "Q Pkts",
399 "Q Pkts", 409 "Q Pkts",
400 "Q Pkts",
401 "Q Pkts"); 410 "Q Pkts");
402 411
403 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); 412 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", "");
404 report.AppendFormat( 413 report.AppendFormat(
405 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", 414 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7}\n",
406 "Last In", 415 "Last In",
407 "In", 416 "In",
408 "Out", 417 "Out",
@@ -414,8 +423,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
414 "Cloud", 423 "Cloud",
415 "Task", 424 "Task",
416 "Texture", 425 "Texture",
417 "Asset", 426 "Asset");
418 "State");
419 427
420 lock (m_scenes) 428 lock (m_scenes)
421 { 429 {
@@ -424,24 +432,24 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
424 scene.ForEachClient( 432 scene.ForEachClient(
425 delegate(IClientAPI client) 433 delegate(IClientAPI client)
426 { 434 {
427 bool isChild = client.SceneAgent.IsChildAgent;
428 if (isChild && !showChildren)
429 return;
430
431 string name = client.Name;
432 if (pname != "" && name != pname)
433 return;
434
435 string regionName = scene.RegionInfo.RegionName;
436
437 report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
438 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
439 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
440
441 if (client is IStatsCollector) 435 if (client is IStatsCollector)
442 { 436 {
443 IStatsCollector stats = (IStatsCollector)client; 437
438 bool isChild = client.SceneAgent.IsChildAgent;
439 if (isChild && !showChildren)
440 return;
444 441
442 string name = client.Name;
443 if (pname != "" && name != pname)
444 return;
445
446 string regionName = scene.RegionInfo.RegionName;
447
448 report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
449 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
450 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
451
452 IStatsCollector stats = (IStatsCollector)client;
445 report.AppendLine(stats.Report()); 453 report.AppendLine(stats.Report());
446 } 454 }
447 }); 455 });
@@ -587,6 +595,115 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
587 (throttleRates.Asset * 8) / 1000); 595 (throttleRates.Asset * 8) / 1000);
588 596
589 return report.ToString(); 597 return report.ToString();
590 } 598 }
599
600 /// <summary>
601 /// Show client stats data
602 /// </summary>
603 /// <param name="showParams"></param>
604 /// <returns></returns>
605 protected string HandleClientStatsReport(string[] showParams)
606 {
607 // NOTE: This writes to m_log on purpose. We want to store this information
608 // in case we need to analyze it later.
609 //
610 if (showParams.Length <= 4)
611 {
612 m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", "Region", "Name", "Root", "Time", "Reqs/min", "AgentUpdates");
613 foreach (Scene scene in m_scenes.Values)
614 {
615 scene.ForEachClient(
616 delegate(IClientAPI client)
617 {
618 if (client is LLClientView)
619 {
620 LLClientView llClient = client as LLClientView;
621 ClientInfo cinfo = llClient.UDPClient.GetClientInfo();
622 int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
623 avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
624
625 string childAgentStatus;
626
627 if (llClient.SceneAgent != null)
628 childAgentStatus = llClient.SceneAgent.IsChildAgent ? "N" : "Y";
629 else
630 childAgentStatus = "Off!";
631
632 m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}",
633 scene.RegionInfo.RegionName, llClient.Name,
634 childAgentStatus,
635 (DateTime.Now - cinfo.StartedTime).Minutes,
636 avg_reqs,
637 string.Format(
638 "{0} ({1:0.00}%)",
639 llClient.TotalAgentUpdates,
640 (float)cinfo.SyncRequests["AgentUpdate"] / llClient.TotalAgentUpdates * 100));
641 }
642 });
643 }
644 return string.Empty;
645 }
646
647 string fname = "", lname = "";
648
649 if (showParams.Length > 3)
650 fname = showParams[3];
651 if (showParams.Length > 4)
652 lname = showParams[4];
653
654 foreach (Scene scene in m_scenes.Values)
655 {
656 scene.ForEachClient(
657 delegate(IClientAPI client)
658 {
659 if (client is LLClientView)
660 {
661 LLClientView llClient = client as LLClientView;
662
663 if (llClient.Name == fname + " " + lname)
664 {
665
666 ClientInfo cinfo = llClient.GetClientInfo();
667 AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(llClient.CircuitCode);
668 if (aCircuit == null) // create a dummy one
669 aCircuit = new AgentCircuitData();
670
671 if (!llClient.SceneAgent.IsChildAgent)
672 m_log.InfoFormat("[INFO]: {0} # {1} # {2}", llClient.Name, aCircuit.Viewer, aCircuit.Id0);
673
674 int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
675 avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
676
677 m_log.InfoFormat("[INFO]:");
678 m_log.InfoFormat("[INFO]: {0} # {1} # Time: {2}min # Avg Reqs/min: {3}", scene.RegionInfo.RegionName,
679 (llClient.SceneAgent.IsChildAgent ? "Child" : "Root"), (DateTime.Now - cinfo.StartedTime).Minutes, avg_reqs);
680
681 Dictionary<string, int> sortedDict = (from entry in cinfo.AsyncRequests orderby entry.Value descending select entry)
682 .ToDictionary(pair => pair.Key, pair => pair.Value);
683 PrintRequests("TOP ASYNC", sortedDict, cinfo.AsyncRequests.Values.Sum());
684
685 sortedDict = (from entry in cinfo.SyncRequests orderby entry.Value descending select entry)
686 .ToDictionary(pair => pair.Key, pair => pair.Value);
687 PrintRequests("TOP SYNC", sortedDict, cinfo.SyncRequests.Values.Sum());
688
689 sortedDict = (from entry in cinfo.GenericRequests orderby entry.Value descending select entry)
690 .ToDictionary(pair => pair.Key, pair => pair.Value);
691 PrintRequests("TOP GENERIC", sortedDict, cinfo.GenericRequests.Values.Sum());
692 }
693 }
694 });
695 }
696 return string.Empty;
697 }
698
699 private void PrintRequests(string type, Dictionary<string, int> sortedDict, int sum)
700 {
701 m_log.InfoFormat("[INFO]:");
702 m_log.InfoFormat("[INFO]: {0,25}", type);
703 foreach (KeyValuePair<string, int> kvp in sortedDict.Take(12))
704 m_log.InfoFormat("[INFO]: {0,25} {1,-6}", kvp.Key, kvp.Value);
705 m_log.InfoFormat("[INFO]: {0,25}", "...");
706 m_log.InfoFormat("[INFO]: {0,25} {1,-6}", "Total", sum);
707 }
591 } 708 }
592} \ No newline at end of file 709} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
index 5a37fad..b5d9fda 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
@@ -461,7 +461,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
461 461
462 string result = instr; 462 string result = instr;
463 463
464 if (result == null || result.Length == 0) 464 if (string.IsNullOrEmpty(result))
465 return result; 465 return result;
466 466
467 // Repeatedly scan the string until all possible 467 // Repeatedly scan the string until all possible
diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
index 018357a..c48e585 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
@@ -375,11 +375,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge
375 scene.GetRootAgentCount(), scene.RegionInfo.RegionName, 375 scene.GetRootAgentCount(), scene.RegionInfo.RegionName,
376 scene.RegionInfo.RegionID, 376 scene.RegionInfo.RegionID,
377 DateTime.UtcNow.ToString("s"))); 377 DateTime.UtcNow.ToString("s")));
378
378 scene.ForEachRootScenePresence(delegate(ScenePresence sp) 379 scene.ForEachRootScenePresence(delegate(ScenePresence sp)
379 { 380 {
380 list.Append(String.Format(" <avatar name=\"{0}\" uuid=\"{1}\" />\n", sp.Name, sp.UUID)); 381 list.Append(String.Format(" <avatar name=\"{0}\" uuid=\"{1}\" />\n", sp.Name, sp.UUID));
381 list.Append("</avatars>");
382 }); 382 });
383
384 list.Append("</avatars>");
383 string payload = list.ToString(); 385 string payload = list.ToString();
384 386
385 // post via REST to broker 387 // post via REST to broker
diff --git a/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs
new file mode 100644
index 0000000..5a6b284
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs
@@ -0,0 +1,220 @@
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 System.Text.RegularExpressions;
34using log4net;
35using Mono.Addins;
36using NDesk.Options;
37using Nini.Config;
38using OpenMetaverse;
39using OpenSim.Framework;
40using OpenSim.Framework.Console;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.OptionalModules.Avatar.SitStand
45{
46 /// <summary>
47 /// A module that just holds commands for changing avatar sitting and standing states.
48 /// </summary>
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AnimationsCommandModule")]
50 public class SitStandCommandModule : INonSharedRegionModule
51 {
52// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private Scene m_scene;
55
56 public string Name { get { return "SitStand Command Module"; } }
57
58 public Type ReplaceableInterface { get { return null; } }
59
60 public void Initialise(IConfigSource source)
61 {
62// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: INITIALIZED MODULE");
63 }
64
65 public void PostInitialise()
66 {
67// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: POST INITIALIZED MODULE");
68 }
69
70 public void Close()
71 {
72// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: CLOSED MODULE");
73 }
74
75 public void AddRegion(Scene scene)
76 {
77// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
78 }
79
80 public void RemoveRegion(Scene scene)
81 {
82// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
83 }
84
85 public void RegionLoaded(Scene scene)
86 {
87// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
88
89 m_scene = scene;
90
91 scene.AddCommand(
92 "Users", this, "sit user name",
93 "sit user name [--regex] <first-name> <last-name>",
94 "Sit the named user on an unoccupied object with a sit target.",
95 "If there are no such objects then nothing happens.\n"
96 + "If --regex is specified then the names are treated as regular expressions.",
97 HandleSitUserNameCommand);
98
99 scene.AddCommand(
100 "Users", this, "stand user name",
101 "stand user name [--regex] <first-name> <last-name>",
102 "Stand the named user.",
103 "If --regex is specified then the names are treated as regular expressions.",
104 HandleStandUserNameCommand);
105 }
106
107 private void HandleSitUserNameCommand(string module, string[] cmd)
108 {
109 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
110 return;
111
112 if (cmd.Length < 5)
113 {
114 MainConsole.Instance.Output("Usage: sit user name [--regex] <first-name> <last-name>");
115 return;
116 }
117
118 List<ScenePresence> scenePresences = GetScenePresences(cmd);
119
120 foreach (ScenePresence sp in scenePresences)
121 {
122 if (sp.SitGround || sp.IsSatOnObject)
123 continue;
124
125 SceneObjectPart sitPart = null;
126 List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups();
127
128 foreach (SceneObjectGroup sceneObject in sceneObjects)
129 {
130 if (sceneObject.IsAttachment)
131 continue;
132
133 foreach (SceneObjectPart part in sceneObject.Parts)
134 {
135 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
136 {
137 sitPart = part;
138 break;
139 }
140 }
141 }
142
143 if (sitPart != null)
144 {
145 MainConsole.Instance.OutputFormat(
146 "Sitting {0} on {1} {2} in {3}",
147 sp.Name, sitPart.ParentGroup.Name, sitPart.ParentGroup.UUID, m_scene.Name);
148
149 sp.HandleAgentRequestSit(sp.ControllingClient, sp.UUID, sitPart.UUID, Vector3.Zero);
150 sp.HandleAgentSit(sp.ControllingClient, sp.UUID);
151 }
152 else
153 {
154 MainConsole.Instance.OutputFormat(
155 "Could not find any unoccupied set seat on which to sit {0} in {1}. Aborting",
156 sp.Name, m_scene.Name);
157
158 break;
159 }
160 }
161 }
162
163 private void HandleStandUserNameCommand(string module, string[] cmd)
164 {
165 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
166 return;
167
168 if (cmd.Length < 5)
169 {
170 MainConsole.Instance.Output("Usage: stand user name [--regex] <first-name> <last-name>");
171 return;
172 }
173
174 List<ScenePresence> scenePresences = GetScenePresences(cmd);
175
176 foreach (ScenePresence sp in scenePresences)
177 {
178 if (sp.SitGround || sp.IsSatOnObject)
179 {
180 MainConsole.Instance.OutputFormat("Standing {0} in {1}", sp.Name, m_scene.Name);
181 sp.StandUp();
182 }
183 }
184 }
185
186 private List<ScenePresence> GetScenePresences(string[] cmdParams)
187 {
188 bool useRegex = false;
189 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
190
191 List<string> mainParams = options.Parse(cmdParams);
192
193 string firstName = mainParams[3];
194 string lastName = mainParams[4];
195
196 List<ScenePresence> scenePresencesMatched = new List<ScenePresence>();
197
198 if (useRegex)
199 {
200 Regex nameRegex = new Regex(string.Format("{0} {1}", firstName, lastName));
201 List<ScenePresence> scenePresences = m_scene.GetScenePresences();
202
203 foreach (ScenePresence sp in scenePresences)
204 {
205 if (!sp.IsChildAgent && nameRegex.IsMatch(sp.Name))
206 scenePresencesMatched.Add(sp);
207 }
208 }
209 else
210 {
211 ScenePresence sp = m_scene.GetScenePresence(firstName, lastName);
212
213 if (sp != null && !sp.IsChildAgent)
214 scenePresencesMatched.Add(sp);
215 }
216
217 return scenePresencesMatched;
218 }
219 }
220} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index 0cec959..2b33084 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -326,15 +326,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
326 "ParcelVoiceInfoRequest", 326 "ParcelVoiceInfoRequest",
327 agentID.ToString())); 327 agentID.ToString()));
328 328
329 caps.RegisterHandler( 329 //caps.RegisterHandler(
330 "ChatSessionRequest", 330 // "ChatSessionRequest",
331 new RestStreamHandler( 331 // new RestStreamHandler(
332 "POST", 332 // "POST",
333 capsBase + m_chatSessionRequestPath, 333 // capsBase + m_chatSessionRequestPath,
334 (request, path, param, httpRequest, httpResponse) 334 // (request, path, param, httpRequest, httpResponse)
335 => ChatSessionRequest(scene, request, path, param, agentID, caps), 335 // => ChatSessionRequest(scene, request, path, param, agentID, caps),
336 "ChatSessionRequest", 336 // "ChatSessionRequest",
337 agentID.ToString())); 337 // agentID.ToString()));
338 } 338 }
339 339
340 /// <summary> 340 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index 9e6cc1a..38ba54d 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -117,6 +117,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
117 117
118 private IConfig m_config; 118 private IConfig m_config;
119 119
120 private object m_Lock;
121
120 public void Initialise(IConfigSource config) 122 public void Initialise(IConfigSource config)
121 { 123 {
122 124
@@ -128,6 +130,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
128 if (!m_config.GetBoolean("enabled", false)) 130 if (!m_config.GetBoolean("enabled", false))
129 return; 131 return;
130 132
133 m_Lock = new object();
134
131 try 135 try
132 { 136 {
133 // retrieve configuration variables 137 // retrieve configuration variables
@@ -429,15 +433,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
429 "ParcelVoiceInfoRequest", 433 "ParcelVoiceInfoRequest",
430 agentID.ToString())); 434 agentID.ToString()));
431 435
432 caps.RegisterHandler( 436 //caps.RegisterHandler(
433 "ChatSessionRequest", 437 // "ChatSessionRequest",
434 new RestStreamHandler( 438 // new RestStreamHandler(
435 "POST", 439 // "POST",
436 capsBase + m_chatSessionRequestPath, 440 // capsBase + m_chatSessionRequestPath,
437 (request, path, param, httpRequest, httpResponse) 441 // (request, path, param, httpRequest, httpResponse)
438 => ChatSessionRequest(scene, request, path, param, agentID, caps), 442 // => ChatSessionRequest(scene, request, path, param, agentID, caps),
439 "ChatSessionRequest", 443 // "ChatSessionRequest",
440 agentID.ToString())); 444 // agentID.ToString()));
441 } 445 }
442 446
443 /// <summary> 447 /// <summary>
@@ -823,11 +827,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
823 { 827 {
824 string requrl = String.Format(m_vivoxChannelPath, m_vivoxServer, "create", channelId, m_authToken); 828 string requrl = String.Format(m_vivoxChannelPath, m_vivoxServer, "create", channelId, m_authToken);
825 829
826 if (parent != null && parent != String.Empty) 830 if (!string.IsNullOrEmpty(parent))
827 { 831 {
828 requrl = String.Format("{0}&chan_parent={1}", requrl, parent); 832 requrl = String.Format("{0}&chan_parent={1}", requrl, parent);
829 } 833 }
830 if (description != null && description != String.Empty) 834 if (!string.IsNullOrEmpty(description))
831 { 835 {
832 requrl = String.Format("{0}&chan_desc={1}", requrl, description); 836 requrl = String.Format("{0}&chan_desc={1}", requrl, description);
833 } 837 }
@@ -837,7 +841,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
837 requrl = String.Format("{0}&chan_roll_off={1}", requrl, m_vivoxChannelRollOff); 841 requrl = String.Format("{0}&chan_roll_off={1}", requrl, m_vivoxChannelRollOff);
838 requrl = String.Format("{0}&chan_dist_model={1}", requrl, m_vivoxChannelDistanceModel); 842 requrl = String.Format("{0}&chan_dist_model={1}", requrl, m_vivoxChannelDistanceModel);
839 requrl = String.Format("{0}&chan_max_range={1}", requrl, m_vivoxChannelMaximumRange); 843 requrl = String.Format("{0}&chan_max_range={1}", requrl, m_vivoxChannelMaximumRange);
840 requrl = String.Format("{0}&chan_ckamping_distance={1}", requrl, m_vivoxChannelClampingDistance); 844 requrl = String.Format("{0}&chan_clamping_distance={1}", requrl, m_vivoxChannelClampingDistance);
841 845
842 XmlElement resp = VivoxCall(requrl, true); 846 XmlElement resp = VivoxCall(requrl, true);
843 if (XmlFind(resp, "response.level0.body.chan_uri", out channelUri)) 847 if (XmlFind(resp, "response.level0.body.chan_uri", out channelUri))
@@ -863,7 +867,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
863 // requrl = String.Format("{0}&chan_parent={1}", requrl, parent); 867 // requrl = String.Format("{0}&chan_parent={1}", requrl, parent);
864 // } 868 // }
865 869
866 if (description != null && description != String.Empty) 870 if (!string.IsNullOrEmpty(description))
867 { 871 {
868 requrl = String.Format("{0}&chan_desc={1}", requrl, description); 872 requrl = String.Format("{0}&chan_desc={1}", requrl, description);
869 } 873 }
@@ -1049,7 +1053,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1049 private XmlElement VivoxDeleteChannel(string parent, string channelid) 1053 private XmlElement VivoxDeleteChannel(string parent, string channelid)
1050 { 1054 {
1051 string requrl = String.Format(m_vivoxChannelDel, m_vivoxServer, "delete", channelid, m_authToken); 1055 string requrl = String.Format(m_vivoxChannelDel, m_vivoxServer, "delete", channelid, m_authToken);
1052 if (parent != null && parent != String.Empty) 1056 if (!string.IsNullOrEmpty(parent))
1053 { 1057 {
1054 requrl = String.Format("{0}&chan_parent={1}", requrl, parent); 1058 requrl = String.Format("{0}&chan_parent={1}", requrl, parent);
1055 } 1059 }
@@ -1118,25 +1122,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1118 1122
1119 doc = new XmlDocument(); 1123 doc = new XmlDocument();
1120 1124
1121 try 1125 // Let's serialize all calls to Vivox. Most of these are driven by
1126 // the clients (CAPs), when the user arrives at the region. We don't
1127 // want to issue many simultaneous http requests to Vivox, because mono
1128 // doesn't like that
1129 lock (m_Lock)
1122 { 1130 {
1123 // Otherwise prepare the request 1131 try
1124// m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl); 1132 {
1133 // Otherwise prepare the request
1134 //m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl);
1125 1135
1126 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl); 1136 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl);
1127 1137
1128 // We are sending just parameters, no content 1138 // We are sending just parameters, no content
1129 req.ContentLength = 0; 1139 req.ContentLength = 0;
1130 1140
1131 // Send request and retrieve the response 1141 // Send request and retrieve the response
1132 using (HttpWebResponse rsp = (HttpWebResponse)req.GetResponse()) 1142 using (HttpWebResponse rsp = (HttpWebResponse)req.GetResponse())
1133 using (Stream s = rsp.GetResponseStream()) 1143 using (Stream s = rsp.GetResponseStream())
1134 using (XmlTextReader rdr = new XmlTextReader(s)) 1144 using (XmlTextReader rdr = new XmlTextReader(s))
1135 doc.Load(rdr); 1145 doc.Load(rdr);
1136 } 1146 }
1137 catch (Exception e) 1147 catch (Exception e)
1138 { 1148 {
1139 m_log.ErrorFormat("[VivoxVoice] Error in admin call : {0}", e.Message); 1149 m_log.ErrorFormat("[VivoxVoice] Error in admin call : {0}", e.Message);
1150 }
1140 } 1151 }
1141 1152
1142 // If we're debugging server responses, dump the whole 1153 // If we're debugging server responses, dump the whole
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index d0a5989..d2a6828 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -39,6 +39,7 @@ using OpenSim.Framework.Communications;
39using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
42using System.Text;
42using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; 43using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
43 44
44namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 45namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
@@ -250,7 +251,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
250 251
251 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; 252 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
252 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; 253 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
253 client.OnDirFindQuery += OnDirFindQuery;
254 client.OnRequestAvatarProperties += OnRequestAvatarProperties; 254 client.OnRequestAvatarProperties += OnRequestAvatarProperties;
255 255
256 // Used for Notices and Group Invites/Accept/Reject 256 // Used for Notices and Group Invites/Accept/Reject
@@ -303,21 +303,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
303 } 303 }
304 */ 304 */
305 305
306 void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart)
307 {
308 if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups)
309 {
310 if (m_debugEnabled)
311 m_log.DebugFormat(
312 "[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})",
313 System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart);
314
315 // TODO: This currently ignores pretty much all the query flags including Mature and sort order
316 remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentID(remoteClient), queryText).ToArray());
317 }
318
319 }
320
321 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) 306 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID)
322 { 307 {
323 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 308 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
@@ -437,44 +422,75 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
437 string Subject = im.message.Substring(0, im.message.IndexOf('|')); 422 string Subject = im.message.Substring(0, im.message.IndexOf('|'));
438 string Message = im.message.Substring(Subject.Length + 1); 423 string Message = im.message.Substring(Subject.Length + 1);
439 424
425 InventoryItemBase item = null;
426 bool hasAttachment = false;
427 UUID itemID = UUID.Zero; //Assignment to quiet compiler
428 UUID ownerID = UUID.Zero; //Assignment to quiet compiler
440 byte[] bucket; 429 byte[] bucket;
441 430
442 if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0)) 431 if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0)
443 {
444 bucket = new byte[19];
445 bucket[0] = 0; //dunno
446 bucket[1] = 0; //dunno
447 GroupID.ToBytes(bucket, 2);
448 bucket[18] = 0; //dunno
449 }
450 else
451 { 432 {
452 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket); 433 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
453 binBucket = binBucket.Remove(0, 14).Trim(); 434 binBucket = binBucket.Remove(0, 14).Trim();
454 if (m_debugEnabled) 435
436 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket);
437 if (binBucketOSD is OSD)
455 { 438 {
456 m_log.WarnFormat("I don't understand a group notice binary bucket of: {0}", binBucket); 439 OSDMap binBucketMap = (OSDMap)binBucketOSD;
440
441 itemID = binBucketMap["item_id"].AsUUID();
442 ownerID = binBucketMap["owner_id"].AsUUID();
457 443
458 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket); 444 //Attempt to get the details of the attached item.
459 445 //If sender doesn't own the attachment, the item
460 foreach (string key in binBucketOSD.Keys) 446 //variable will be set to null and attachment will
447 //not be included with the group notice.
448 Scene scene = (Scene)remoteClient.Scene;
449 item = new InventoryItemBase(itemID, ownerID);
450 item = scene.InventoryService.GetItem(item);
451
452 if (item != null)
461 { 453 {
462 if (binBucketOSD.ContainsKey(key)) 454 //Got item details so include the attachment.
463 { 455 hasAttachment = true;
464 m_log.WarnFormat("{0}: {1}", key, binBucketOSD[key].ToString());
465 }
466 } 456 }
467 } 457 }
468 458 else
469 // treat as if no attachment 459 {
460 m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType());
461 }
462 }
463
464 if (hasAttachment)
465 {
466 //Bucket contains information about attachment.
467 //
468 //Byte offset and description of bucket data:
469 //0: 1 byte indicating if attachment is present
470 //1: 1 byte indicating the type of attachment
471 //2: 16 bytes - Group UUID
472 //18: 16 bytes - UUID of the attachment owner
473 //34: 16 bytes - UUID of the attachment
474 //50: variable - Name of the attachment
475 //??: NUL byte to terminate the attachment name
476 byte[] name = Encoding.UTF8.GetBytes(item.Name);
477 bucket = new byte[51 + name.Length];//3 bytes, 3 UUIDs, and name
478 bucket[0] = 1; //Has attachment flag
479 bucket[1] = (byte)item.InvType; //Type of Attachment
480 GroupID.ToBytes(bucket, 2);
481 ownerID.ToBytes(bucket, 18);
482 itemID.ToBytes(bucket, 34);
483 name.CopyTo(bucket, 50);
484 }
485 else
486 {
470 bucket = new byte[19]; 487 bucket = new byte[19];
471 bucket[0] = 0; //dunno 488 bucket[0] = 0; //Has attachment flag
472 bucket[1] = 0; //dunno 489 bucket[1] = 0; //Type of attachment
473 GroupID.ToBytes(bucket, 2); 490 GroupID.ToBytes(bucket, 2);
474 bucket[18] = 0; //dunno 491 bucket[18] = 0; //NUL terminate name of attachment
475 } 492 }
476 493
477
478 m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); 494 m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket);
479 if (OnNewGroupNotice != null) 495 if (OnNewGroupNotice != null)
480 { 496 {
@@ -499,7 +515,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
499 515
500 if (member.AcceptNotices) 516 if (member.AcceptNotices)
501 { 517 {
502 // Build notice IIM 518 // Build notice IM
503 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); 519 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
504 520
505 msg.toAgentID = member.AgentID.Guid; 521 msg.toAgentID = member.AgentID.Guid;
@@ -508,10 +524,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
508 } 524 }
509 } 525 }
510 } 526 }
511 527
528 if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted)
529 {
530 //Is bucket large enough to hold UUID of the attachment?
531 if (im.binaryBucket.Length < 16)
532 return;
533
534 UUID noticeID = new UUID(im.imSessionID);
535
536 GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID);
537 if (notice != null)
538 {
539 UUID giver = new UUID(notice.BinaryBucket, 18);
540 UUID attachmentUUID = new UUID(notice.BinaryBucket, 34);
541
542 if (m_debugEnabled)
543 m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId);
544
545 InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId,
546 giver, attachmentUUID);
547
548 if (itemCopy == null)
549 {
550 remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false);
551 return;
552 }
553
554 remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
555 }
556 }
557
512 // Interop, received special 210 code for ejecting a group member 558 // Interop, received special 210 code for ejecting a group member
513 // this only works within the comms servers domain, and won't work hypergrid 559 // this only works within the comms servers domain, and won't work hypergrid
514 // TODO:FIXME: Use a presense server of some kind to find out where the 560 // TODO:FIXME: Use a presence server of some kind to find out where the
515 // client actually is, and try contacting that region directly to notify them, 561 // client actually is, and try contacting that region directly to notify them,
516 // or provide the notification via xmlrpc update queue 562 // or provide the notification via xmlrpc update queue
517 if ((im.dialog == 210)) 563 if ((im.dialog == 210))
@@ -889,26 +935,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
889 935
890 if (data != null) 936 if (data != null)
891 { 937 {
892 GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); 938 GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested);
893
894 GridInstantMessage msg = new GridInstantMessage();
895 msg.imSessionID = UUID.Zero.Guid;
896 msg.fromAgentID = data.GroupID.Guid;
897 msg.toAgentID = GetRequestingAgentID(remoteClient).Guid;
898 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
899 msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName;
900 msg.message = data.noticeData.Subject + "|" + data.Message;
901 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested;
902 msg.fromGroup = true;
903 msg.offline = (byte)0;
904 msg.ParentEstateID = 0;
905 msg.Position = Vector3.Zero;
906 msg.RegionID = UUID.Zero.Guid;
907 msg.binaryBucket = data.BinaryBucket;
908 939
909 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); 940 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient));
910 } 941 }
911
912 } 942 }
913 943
914 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog) 944 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog)
@@ -916,10 +946,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
916 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 946 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
917 947
918 GridInstantMessage msg = new GridInstantMessage(); 948 GridInstantMessage msg = new GridInstantMessage();
919 msg.imSessionID = UUID.Zero.Guid; 949 byte[] bucket;
950
951 msg.imSessionID = groupNoticeID.Guid;
920 msg.toAgentID = agentID.Guid; 952 msg.toAgentID = agentID.Guid;
921 msg.dialog = dialog; 953 msg.dialog = dialog;
922 // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice;
923 msg.fromGroup = true; 954 msg.fromGroup = true;
924 msg.offline = (byte)1; // Allow this message to be stored for offline use 955 msg.offline = (byte)1; // Allow this message to be stored for offline use
925 msg.ParentEstateID = 0; 956 msg.ParentEstateID = 0;
@@ -933,13 +964,38 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
933 msg.timestamp = info.noticeData.Timestamp; 964 msg.timestamp = info.noticeData.Timestamp;
934 msg.fromAgentName = info.noticeData.FromName; 965 msg.fromAgentName = info.noticeData.FromName;
935 msg.message = info.noticeData.Subject + "|" + info.Message; 966 msg.message = info.noticeData.Subject + "|" + info.Message;
936 msg.binaryBucket = info.BinaryBucket; 967
968 if (info.BinaryBucket[0] > 0)
969 {
970 //32 is due to not needing space for two of the UUIDs.
971 //(Don't need UUID of attachment or its owner in IM)
972 //50 offset gets us to start of attachment name.
973 //We are skipping the attachment flag, type, and
974 //the three UUID fields at the start of the bucket.
975 bucket = new byte[info.BinaryBucket.Length-32];
976 bucket[0] = 1; //Has attachment
977 bucket[1] = info.BinaryBucket[1];
978 Array.Copy(info.BinaryBucket, 50,
979 bucket, 18, info.BinaryBucket.Length-50);
980 }
981 else
982 {
983 bucket = new byte[19];
984 bucket[0] = 0; //No attachment
985 bucket[1] = 0; //Attachment type
986 bucket[18] = 0; //NUL terminate name
987 }
988
989 info.GroupID.ToBytes(bucket, 2);
990 msg.binaryBucket = bucket;
937 } 991 }
938 else 992 else
939 { 993 {
940 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID); 994 if (m_debugEnabled)
995 m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID);
996
941 msg.fromAgentID = UUID.Zero.Guid; 997 msg.fromAgentID = UUID.Zero.Guid;
942 msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); ; 998 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
943 msg.fromAgentName = string.Empty; 999 msg.fromAgentName = string.Empty;
944 msg.message = string.Empty; 1000 msg.message = string.Empty;
945 msg.binaryBucket = new byte[0]; 1001 msg.binaryBucket = new byte[0];
@@ -1063,7 +1119,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1063 // Message to ejector 1119 // Message to ejector
1064 // Interop, received special 210 code for ejecting a group member 1120 // Interop, received special 210 code for ejecting a group member
1065 // this only works within the comms servers domain, and won't work hypergrid 1121 // this only works within the comms servers domain, and won't work hypergrid
1066 // TODO:FIXME: Use a presense server of some kind to find out where the 1122 // TODO:FIXME: Use a presence server of some kind to find out where the
1067 // client actually is, and try contacting that region directly to notify them, 1123 // client actually is, and try contacting that region directly to notify them,
1068 // or provide the notification via xmlrpc update queue 1124 // or provide the notification via xmlrpc update queue
1069 1125
@@ -1178,6 +1234,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1178 } 1234 }
1179 } 1235 }
1180 1236
1237 public List<DirGroupsReplyData> FindGroups(IClientAPI remoteClient, string query)
1238 {
1239 return m_groupData.FindGroups(GetRequestingAgentID(remoteClient), query);
1240 }
1241
1242
1181 #endregion 1243 #endregion
1182 1244
1183 #region Client/Update Tools 1245 #region Client/Update Tools
@@ -1222,7 +1284,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1222 AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); 1284 AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID));
1223 AgentData.Add(AgentDataMap); 1285 AgentData.Add(AgentDataMap);
1224 1286
1225
1226 OSDArray GroupData = new OSDArray(data.Length); 1287 OSDArray GroupData = new OSDArray(data.Length);
1227 OSDArray NewGroupData = new OSDArray(data.Length); 1288 OSDArray NewGroupData = new OSDArray(data.Length);
1228 1289
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
index 7bae8f7..8095b28 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
@@ -212,8 +212,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
212 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name); 212 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
213 213
214 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); 214 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
215 if ((m_groupsServerURI == null) || 215 if (string.IsNullOrEmpty(m_groupsServerURI))
216 (m_groupsServerURI == string.Empty))
217 { 216 {
218 m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]"); 217 m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]");
219 m_connectorEnabled = false; 218 m_connectorEnabled = false;
@@ -438,7 +437,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
438 return null; 437 return null;
439 } 438 }
440 } 439 }
441 else if ((groupName != null) && (groupName != string.Empty)) 440 else if (!string.IsNullOrEmpty(groupName))
442 { 441 {
443 if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap)) 442 if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap))
444 { 443 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
index c1bdacb..26d2597 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
@@ -26,13 +26,23 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Net;
29using System.Reflection; 31using System.Reflection;
30using Nini.Config; 32using Nini.Config;
31using NUnit.Framework; 33using NUnit.Framework;
32using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.Messages.Linden;
36using OpenMetaverse.Packets;
37using OpenMetaverse.StructuredData;
33using OpenSim.Framework; 38using OpenSim.Framework;
34using OpenSim.Framework.Communications; 39using OpenSim.Framework.Communications;
40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.ClientStack.Linden;
43using OpenSim.Region.CoreModules.Framework;
35using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
45using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups;
36using OpenSim.Tests.Common; 46using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock; 47using OpenSim.Tests.Common.Mock;
38 48
@@ -44,11 +54,28 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
44 [TestFixture] 54 [TestFixture]
45 public class GroupsModuleTests : OpenSimTestCase 55 public class GroupsModuleTests : OpenSimTestCase
46 { 56 {
57 [SetUp]
58 public override void SetUp()
59 {
60 base.SetUp();
61
62 uint port = 9999;
63 uint sslPort = 9998;
64
65 // This is an unfortunate bit of clean up we have to do because MainServer manages things through static
66 // variables and the VM is not restarted between tests.
67 MainServer.RemoveHttpServer(port);
68
69 BaseHttpServer server = new BaseHttpServer(port, false, sslPort, "");
70 MainServer.AddHttpServer(server);
71 MainServer.Instance = server;
72 }
73
47 [Test] 74 [Test]
48 public void TestBasic() 75 public void TestSendAgentGroupDataUpdate()
49 { 76 {
50 TestHelpers.InMethod(); 77 TestHelpers.InMethod();
51// log4net.Config.XmlConfigurator.Configure(); 78// TestHelpers.EnableLogging();
52 79
53 TestScene scene = new SceneHelpers().SetupScene(); 80 TestScene scene = new SceneHelpers().SetupScene();
54 IConfigSource configSource = new IniConfigSource(); 81 IConfigSource configSource = new IniConfigSource();
@@ -56,8 +83,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
56 config.Set("Enabled", true); 83 config.Set("Enabled", true);
57 config.Set("Module", "GroupsModule"); 84 config.Set("Module", "GroupsModule");
58 config.Set("DebugEnabled", true); 85 config.Set("DebugEnabled", true);
86
87 GroupsModule gm = new GroupsModule();
88 EventQueueGetModule eqgm = new EventQueueGetModule();
89
90 // We need a capabilities module active so that adding the scene presence creates an event queue in the
91 // EventQueueGetModule
59 SceneHelpers.SetupSceneModules( 92 SceneHelpers.SetupSceneModules(
60 scene, configSource, new object[] { new MockGroupsServicesConnector() }); 93 scene, configSource, gm, new MockGroupsServicesConnector(), new CapabilitiesModule(), eqgm);
94
95 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseStem("1"));
96
97 gm.SendAgentGroupDataUpdate(sp.ControllingClient);
98
99 Hashtable eventsResponse = eqgm.GetEvents(UUID.Zero, sp.UUID);
100
101 Assert.That((int)eventsResponse["int_response_code"], Is.EqualTo((int)HttpStatusCode.OK));
102
103// Console.WriteLine("Response [{0}]", (string)eventsResponse["str_response_string"]);
104
105 OSDMap rawOsd = (OSDMap)OSDParser.DeserializeLLSDXml((string)eventsResponse["str_response_string"]);
106 OSDArray eventsOsd = (OSDArray)rawOsd["events"];
107
108 bool foundUpdate = false;
109 foreach (OSD osd in eventsOsd)
110 {
111 OSDMap eventOsd = (OSDMap)osd;
112
113 if (eventOsd["message"] == "AgentGroupDataUpdate")
114 foundUpdate = true;
115 }
116
117 Assert.That(foundUpdate, Is.True, "Did not find AgentGroupDataUpdate in response");
118
119 // TODO: More checking of more actual event data.
61 } 120 }
62 } 121 }
63} \ No newline at end of file 122} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
index 71b24ac..e28d0c2 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
@@ -168,8 +168,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
168 m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name); 168 m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
169 169
170 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); 170 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
171 if ((m_groupsServerURI == null) || 171 if (string.IsNullOrEmpty(m_groupsServerURI))
172 (m_groupsServerURI == string.Empty))
173 { 172 {
174 m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]"); 173 m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]");
175 m_connectorEnabled = false; 174 m_connectorEnabled = false;
@@ -354,7 +353,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
354 { 353 {
355 param["GroupID"] = GroupID.ToString(); 354 param["GroupID"] = GroupID.ToString();
356 } 355 }
357 if ((GroupName != null) && (GroupName != string.Empty)) 356 if (!string.IsNullOrEmpty(GroupName))
358 { 357 {
359 param["Name"] = GroupName.ToString(); 358 param["Name"] = GroupName.ToString();
360 } 359 }
diff --git a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs b/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs
deleted file mode 100644
index 6e74ce0..0000000
--- a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs
+++ /dev/null
@@ -1,339 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Diagnostics;
31using System.Linq;
32using System.Net.NetworkInformation;
33using System.Text;
34using System.Threading;
35
36using log4net;
37using Mono.Addins;
38using Nini.Config;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Console;
42using OpenSim.Framework.Monitoring;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45
46using OpenMetaverse.StructuredData;
47
48namespace OpenSim.Region.OptionalModules.Framework.Monitoring
49{
50[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ServerStatistics")]
51public class ServerStats : ISharedRegionModule
52{
53 private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
54 private readonly string LogHeader = "[SERVER STATS]";
55
56 public bool Enabled = false;
57 private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
58
59 public readonly string CategoryServer = "server";
60
61 public readonly string ContainerProcessor = "processor";
62 public readonly string ContainerMemory = "memory";
63 public readonly string ContainerNetwork = "network";
64 public readonly string ContainerProcess = "process";
65
66 public string NetworkInterfaceTypes = "Ethernet";
67
68 readonly int performanceCounterSampleInterval = 500;
69 int lastperformanceCounterSampleTime = 0;
70
71 private class PerfCounterControl
72 {
73 public PerformanceCounter perfCounter;
74 public int lastFetch;
75 public string name;
76 public PerfCounterControl(PerformanceCounter pPc)
77 : this(pPc, String.Empty)
78 {
79 }
80 public PerfCounterControl(PerformanceCounter pPc, string pName)
81 {
82 perfCounter = pPc;
83 lastFetch = 0;
84 name = pName;
85 }
86 }
87
88 PerfCounterControl processorPercentPerfCounter = null;
89
90 #region ISharedRegionModule
91 // IRegionModuleBase.Name
92 public string Name { get { return "Server Stats"; } }
93 // IRegionModuleBase.ReplaceableInterface
94 public Type ReplaceableInterface { get { return null; } }
95 // IRegionModuleBase.Initialize
96 public void Initialise(IConfigSource source)
97 {
98 IConfig cfg = source.Configs["Monitoring"];
99
100 if (cfg != null)
101 Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
102
103 if (Enabled)
104 {
105 NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
106 }
107 }
108 // IRegionModuleBase.Close
109 public void Close()
110 {
111 if (RegisteredStats.Count > 0)
112 {
113 foreach (Stat stat in RegisteredStats.Values)
114 {
115 StatsManager.DeregisterStat(stat);
116 stat.Dispose();
117 }
118 RegisteredStats.Clear();
119 }
120 }
121 // IRegionModuleBase.AddRegion
122 public void AddRegion(Scene scene)
123 {
124 }
125 // IRegionModuleBase.RemoveRegion
126 public void RemoveRegion(Scene scene)
127 {
128 }
129 // IRegionModuleBase.RegionLoaded
130 public void RegionLoaded(Scene scene)
131 {
132 }
133 // ISharedRegionModule.PostInitialize
134 public void PostInitialise()
135 {
136 if (RegisteredStats.Count == 0)
137 {
138 RegisterServerStats();
139 }
140 }
141 #endregion ISharedRegionModule
142
143 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
144 {
145 string desc = pDesc;
146 if (desc == null)
147 desc = pName;
148 Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info);
149 StatsManager.RegisterStat(stat);
150 RegisteredStats.Add(pName, stat);
151 }
152
153 public void RegisterServerStats()
154 {
155 lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
156 PerformanceCounter tempPC;
157 Stat tempStat;
158 string tempName;
159
160 try
161 {
162 tempName = "CPUPercent";
163 tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
164 processorPercentPerfCounter = new PerfCounterControl(tempPC);
165 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
166 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
167 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
168 StatVerbosity.Info);
169 StatsManager.RegisterStat(tempStat);
170 RegisteredStats.Add(tempName, tempStat);
171
172 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
173 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
174
175 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
176 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
177
178 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
179 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
180
181 MakeStat("Threads", null, "threads", ContainerProcessor,
182 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
183 }
184 catch (Exception e)
185 {
186 m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
187 }
188
189 try
190 {
191 List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
192
193 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
194 foreach (NetworkInterface nic in nics)
195 {
196 if (nic.OperationalStatus != OperationalStatus.Up)
197 continue;
198
199 string nicInterfaceType = nic.NetworkInterfaceType.ToString();
200 if (!okInterfaceTypes.Contains(nicInterfaceType))
201 {
202 m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
203 LogHeader, nic.Name, nicInterfaceType);
204 m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
205 LogHeader, NetworkInterfaceTypes);
206 continue;
207 }
208
209 if (nic.Supports(NetworkInterfaceComponent.IPv4))
210 {
211 IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
212 if (nicStats != null)
213 {
214 MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
215 (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
216 MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
217 (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
218 MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
219 (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
220 }
221 }
222 // TODO: add IPv6 (it may actually happen someday)
223 }
224 }
225 catch (Exception e)
226 {
227 m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
228 }
229
230 MakeStat("ProcessMemory", null, "MB", ContainerMemory,
231 (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; });
232 MakeStat("ObjectMemory", null, "MB", ContainerMemory,
233 (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; });
234 MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory,
235 (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); });
236 MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory,
237 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); });
238 }
239
240 // Notes on performance counters:
241 // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
242 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
243 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
244 private delegate double PerfCounterNextValue();
245 private void GetNextValue(Stat stat, PerfCounterControl perfControl)
246 {
247 GetNextValue(stat, perfControl, 1.0);
248 }
249 private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
250 {
251 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
252 {
253 if (perfControl != null && perfControl.perfCounter != null)
254 {
255 try
256 {
257 // Kludge for factor to run double duty. If -1, subtract the value from one
258 if (factor == -1)
259 stat.Value = 1 - perfControl.perfCounter.NextValue();
260 else
261 stat.Value = perfControl.perfCounter.NextValue() / factor;
262 }
263 catch (Exception e)
264 {
265 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
266 }
267 perfControl.lastFetch = Util.EnvironmentTickCount();
268 }
269 }
270 }
271
272 // Lookup the nic that goes with this stat and set the value by using a fetch action.
273 // Not sure about closure with delegates inside delegates.
274 private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
275 private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
276 {
277 // Get the one nic that has the name of this stat
278 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
279 (network) => network.Name == stat.Description);
280 try
281 {
282 foreach (NetworkInterface nic in nics)
283 {
284 IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
285 if (intrStats != null)
286 {
287 double newVal = Math.Round(getter(intrStats) / factor, 3);
288 stat.Value = newVal;
289 }
290 break;
291 }
292 }
293 catch
294 {
295 // There are times interfaces go away so we just won't update the stat for this
296 m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
297 }
298 }
299}
300
301public class ServerStatsAggregator : Stat
302{
303 public ServerStatsAggregator(
304 string shortName,
305 string name,
306 string description,
307 string unitName,
308 string category,
309 string container
310 )
311 : base(
312 shortName,
313 name,
314 description,
315 unitName,
316 category,
317 container,
318 StatType.Push,
319 MeasuresOfInterest.None,
320 null,
321 StatVerbosity.Info)
322 {
323 }
324 public override string ToConsoleString()
325 {
326 StringBuilder sb = new StringBuilder();
327
328 return sb.ToString();
329 }
330
331 public override OSDMap ToOSDMap()
332 {
333 OSDMap ret = new OSDMap();
334
335 return ret;
336 }
337}
338
339}
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
new file mode 100644
index 0000000..afb788b
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -0,0 +1,590 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Security.Cryptography; // for computing md5 hash
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
46
47using Ionic.Zlib;
48
49// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
50// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
51// the available DLLs
52//[assembly: Addin("MaterialsModule", "1.0")]
53//[assembly: AddinDependency("OpenSim", "0.5")]
54
55namespace OpenSim.Region.OptionalModules.Materials
56{
57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")]
58 public class MaterialsModule : INonSharedRegionModule
59 {
60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61
62 public string Name { get { return "MaterialsModule"; } }
63
64 public Type ReplaceableInterface { get { return null; } }
65
66 private Scene m_scene = null;
67 private bool m_enabled = false;
68
69 public Dictionary<UUID, OSDMap> m_regionMaterials = new Dictionary<UUID, OSDMap>();
70
71 public void Initialise(IConfigSource source)
72 {
73 IConfig config = source.Configs["Materials"];
74 if (config == null)
75 return;
76
77 m_enabled = config.GetBoolean("enable_materials", true);
78 if (!m_enabled)
79 return;
80
81 m_log.DebugFormat("[Materials]: Initialized");
82 }
83
84 public void Close()
85 {
86 if (!m_enabled)
87 return;
88 }
89
90 public void AddRegion(Scene scene)
91 {
92 if (!m_enabled)
93 return;
94
95 m_scene = scene;
96 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
97 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
98 }
99
100 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
101 {
102 foreach (var part in obj.Parts)
103 if (part != null)
104 GetStoredMaterialsInPart(part);
105 }
106
107 private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
108 {
109 string capsBase = "/CAPS/" + caps.CapsObjectPath;
110
111 IRequestHandler renderMaterialsPostHandler
112 = new RestStreamHandler("POST", capsBase + "/",
113 (request, path, param, httpRequest, httpResponse)
114 => RenderMaterialsPostCap(request, agentID),
115 "RenderMaterials", null);
116 caps.RegisterHandler("RenderMaterials", renderMaterialsPostHandler);
117
118 // OpenSimulator CAPs infrastructure seems to be somewhat hostile towards any CAP that requires both GET
119 // and POST handlers, (at least at the time this was originally written), so we first set up a POST
120 // handler normally and then add a GET handler via MainServer
121
122 IRequestHandler renderMaterialsGetHandler
123 = new RestStreamHandler("GET", capsBase + "/",
124 (request, path, param, httpRequest, httpResponse)
125 => RenderMaterialsGetCap(request),
126 "RenderMaterials", null);
127 MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
128
129 // materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well
130 IRequestHandler renderMaterialsPutHandler
131 = new RestStreamHandler("PUT", capsBase + "/",
132 (request, path, param, httpRequest, httpResponse)
133 => RenderMaterialsPostCap(request, agentID),
134 "RenderMaterials", null);
135 MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
136 }
137
138 public void RemoveRegion(Scene scene)
139 {
140 if (!m_enabled)
141 return;
142
143 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
144 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
145 }
146
147 public void RegionLoaded(Scene scene)
148 {
149 }
150
151 /// <summary>
152 /// Finds any legacy materials stored in DynAttrs that may exist for this part and add them to 'm_regionMaterials'.
153 /// </summary>
154 /// <param name="part"></param>
155 private void GetLegacyStoredMaterialsInPart(SceneObjectPart part)
156 {
157 if (part.DynAttrs == null)
158 return;
159
160 OSD OSMaterials = null;
161 OSDArray matsArr = null;
162
163 lock (part.DynAttrs)
164 {
165 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
166 {
167 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
168
169 if (materialsStore == null)
170 return;
171
172 materialsStore.TryGetValue("Materials", out OSMaterials);
173 }
174
175 if (OSMaterials != null && OSMaterials is OSDArray)
176 matsArr = OSMaterials as OSDArray;
177 else
178 return;
179 }
180
181 if (matsArr == null)
182 return;
183
184 foreach (OSD elemOsd in matsArr)
185 {
186 if (elemOsd != null && elemOsd is OSDMap)
187 {
188 OSDMap matMap = elemOsd as OSDMap;
189 if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
190 {
191 try
192 {
193 lock (m_regionMaterials)
194 m_regionMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
195 }
196 catch (Exception e)
197 {
198 m_log.Warn("[Materials]: exception decoding persisted legacy material: " + e.ToString());
199 }
200 }
201 }
202 }
203 }
204
205 /// <summary>
206 /// Find the materials used in the SOP, and add them to 'm_regionMaterials'.
207 /// </summary>
208 private void GetStoredMaterialsInPart(SceneObjectPart part)
209 {
210 if (part.Shape == null)
211 return;
212
213 var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
214 if (te == null)
215 return;
216
217 GetLegacyStoredMaterialsInPart(part);
218
219 GetStoredMaterialInFace(part, te.DefaultTexture);
220
221 foreach (Primitive.TextureEntryFace face in te.FaceTextures)
222 {
223 if (face != null)
224 GetStoredMaterialInFace(part, face);
225 }
226 }
227
228 /// <summary>
229 /// Find the materials used in one Face, and add them to 'm_regionMaterials'.
230 /// </summary>
231 private void GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face)
232 {
233 UUID id = face.MaterialID;
234 if (id == UUID.Zero)
235 return;
236
237 lock (m_regionMaterials)
238 {
239 if (m_regionMaterials.ContainsKey(id))
240 return;
241
242 byte[] data = m_scene.AssetService.GetData(id.ToString());
243 if (data == null)
244 {
245 m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id);
246 return;
247 }
248
249 OSDMap mat;
250 try
251 {
252 mat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
253 }
254 catch (Exception e)
255 {
256 m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message);
257 return;
258 }
259
260 m_regionMaterials[id] = mat;
261 }
262 }
263
264 public string RenderMaterialsPostCap(string request, UUID agentID)
265 {
266 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
267 OSDMap resp = new OSDMap();
268
269 OSDMap materialsFromViewer = null;
270
271 OSDArray respArr = new OSDArray();
272
273 if (req.ContainsKey("Zipped"))
274 {
275 OSD osd = null;
276
277 byte[] inBytes = req["Zipped"].AsBinary();
278
279 try
280 {
281 osd = ZDecompressBytesToOsd(inBytes);
282
283 if (osd != null)
284 {
285 if (osd is OSDArray) // assume array of MaterialIDs designating requested material entries
286 {
287 foreach (OSD elem in (OSDArray)osd)
288 {
289 try
290 {
291 UUID id = new UUID(elem.AsBinary(), 0);
292
293 lock (m_regionMaterials)
294 {
295 if (m_regionMaterials.ContainsKey(id))
296 {
297 OSDMap matMap = new OSDMap();
298 matMap["ID"] = OSD.FromBinary(id.GetBytes());
299 matMap["Material"] = m_regionMaterials[id];
300 respArr.Add(matMap);
301 }
302 else
303 {
304 m_log.Warn("[Materials]: request for unknown material ID: " + id.ToString());
305
306 // Theoretically we could try to load the material from the assets service,
307 // but that shouldn't be necessary because the viewer should only request
308 // materials that exist in a prim on the region, and all of these materials
309 // are already stored in m_regionMaterials.
310 }
311 }
312 }
313 catch (Exception e)
314 {
315 m_log.Error("Error getting materials in response to viewer request", e);
316 continue;
317 }
318 }
319 }
320 else if (osd is OSDMap) // request to assign a material
321 {
322 materialsFromViewer = osd as OSDMap;
323
324 if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
325 {
326 OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
327 if (matsOsd is OSDArray)
328 {
329 OSDArray matsArr = matsOsd as OSDArray;
330
331 try
332 {
333 foreach (OSDMap matsMap in matsArr)
334 {
335 uint primLocalID = 0;
336 try {
337 primLocalID = matsMap["ID"].AsUInteger();
338 }
339 catch (Exception e) {
340 m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message);
341 continue;
342 }
343
344 OSDMap mat = null;
345 try
346 {
347 mat = matsMap["Material"] as OSDMap;
348 }
349 catch (Exception e)
350 {
351 m_log.Warn("[Materials]: cannot decode \"Material\" from matsMap: " + e.Message);
352 continue;
353 }
354
355 SceneObjectPart sop = m_scene.GetSceneObjectPart(primLocalID);
356 if (sop == null)
357 {
358 m_log.WarnFormat("[Materials]: SOP not found for localId: {0}", primLocalID.ToString());
359 continue;
360 }
361
362 if (!m_scene.Permissions.CanEditObject(sop.UUID, agentID))
363 {
364 m_log.WarnFormat("User {0} can't edit object {1} {2}", agentID, sop.Name, sop.UUID);
365 continue;
366 }
367
368 Primitive.TextureEntry te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
369 if (te == null)
370 {
371 m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID);
372 continue;
373 }
374
375
376 UUID id;
377 if (mat == null)
378 {
379 // This happens then the user removes a material from a prim
380 id = UUID.Zero;
381 }
382 else
383 {
384 id = StoreMaterialAsAsset(agentID, mat, sop);
385 }
386
387
388 int face = -1;
389
390 if (matsMap.ContainsKey("Face"))
391 {
392 face = matsMap["Face"].AsInteger();
393 Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
394 faceEntry.MaterialID = id;
395 }
396 else
397 {
398 if (te.DefaultTexture == null)
399 m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
400 else
401 te.DefaultTexture.MaterialID = id;
402 }
403
404 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
405
406 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
407 sop.Shape.TextureEntry = te.GetBytes();
408
409 if (sop.ParentGroup != null)
410 {
411 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
412 sop.UpdateFlag = UpdateRequired.FULL;
413 sop.ParentGroup.HasGroupChanged = true;
414 sop.ScheduleFullUpdate();
415 }
416 }
417 }
418 catch (Exception e)
419 {
420 m_log.Warn("[Materials]: exception processing received material ", e);
421 }
422 }
423 }
424 }
425 }
426
427 }
428 catch (Exception e)
429 {
430 m_log.Warn("[Materials]: exception decoding zipped CAP payload ", e);
431 //return "";
432 }
433 }
434
435
436 resp["Zipped"] = ZCompressOSD(respArr, false);
437 string response = OSDParser.SerializeLLSDXmlString(resp);
438
439 //m_log.Debug("[Materials]: cap request: " + request);
440 //m_log.Debug("[Materials]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
441 //m_log.Debug("[Materials]: cap response: " + response);
442 return response;
443 }
444
445 private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
446 {
447 UUID id;
448 // Material UUID = hash of the material's data.
449 // This makes materials deduplicate across the entire grid (but isn't otherwise required).
450 byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
451 using (var md5 = MD5.Create())
452 id = new UUID(md5.ComputeHash(data), 0);
453
454 lock (m_regionMaterials)
455 {
456 if (!m_regionMaterials.ContainsKey(id))
457 {
458 m_regionMaterials[id] = mat;
459
460 // This asset might exist already, but it's ok to try to store it again
461 string name = "Material " + ChooseMaterialName(mat, sop);
462 name = name.Substring(0, Math.Min(64, name.Length)).Trim();
463 AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
464 asset.Data = data;
465 m_scene.AssetService.Store(asset);
466 }
467 }
468 return id;
469 }
470
471 /// <summary>
472 /// Use heuristics to choose a good name for the material.
473 /// </summary>
474 private string ChooseMaterialName(OSDMap mat, SceneObjectPart sop)
475 {
476 UUID normMap = mat["NormMap"].AsUUID();
477 if (normMap != UUID.Zero)
478 {
479 AssetBase asset = m_scene.AssetService.GetCached(normMap.ToString());
480 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
481 return asset.Name;
482 }
483
484 UUID specMap = mat["SpecMap"].AsUUID();
485 if (specMap != UUID.Zero)
486 {
487 AssetBase asset = m_scene.AssetService.GetCached(specMap.ToString());
488 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
489 return asset.Name;
490 }
491
492 if (sop.Name != "Primitive")
493 return sop.Name;
494
495 if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive"))
496 return sop.ParentGroup.Name;
497
498 return "";
499 }
500
501
502 public string RenderMaterialsGetCap(string request)
503 {
504 OSDMap resp = new OSDMap();
505 int matsCount = 0;
506 OSDArray allOsd = new OSDArray();
507
508 lock (m_regionMaterials)
509 {
510 foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials)
511 {
512 OSDMap matMap = new OSDMap();
513
514 matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
515 matMap["Material"] = kvp.Value;
516 allOsd.Add(matMap);
517 matsCount++;
518 }
519 }
520
521 resp["Zipped"] = ZCompressOSD(allOsd, false);
522
523 return OSDParser.SerializeLLSDXmlString(resp);
524 }
525
526 private static string ZippedOsdBytesToString(byte[] bytes)
527 {
528 try
529 {
530 return OSDParser.SerializeJsonString(ZDecompressBytesToOsd(bytes));
531 }
532 catch (Exception e)
533 {
534 return "ZippedOsdBytesToString caught an exception: " + e.ToString();
535 }
536 }
537
538 /// <summary>
539 /// computes a UUID by hashing a OSD object
540 /// </summary>
541 /// <param name="osd"></param>
542 /// <returns></returns>
543 private static UUID HashOsd(OSD osd)
544 {
545 byte[] data = OSDParser.SerializeLLSDBinary(osd, false);
546 using (var md5 = MD5.Create())
547 return new UUID(md5.ComputeHash(data), 0);
548 }
549
550 public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
551 {
552 OSD osd = null;
553
554 byte[] data = OSDParser.SerializeLLSDBinary(inOsd, useHeader);
555
556 using (MemoryStream msSinkCompressed = new MemoryStream())
557 {
558 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
559 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
560 {
561 zOut.Write(data, 0, data.Length);
562 }
563
564 msSinkCompressed.Seek(0L, SeekOrigin.Begin);
565 osd = OSD.FromBinary(msSinkCompressed.ToArray());
566 }
567
568 return osd;
569 }
570
571
572 public static OSD ZDecompressBytesToOsd(byte[] input)
573 {
574 OSD osd = null;
575
576 using (MemoryStream msSinkUnCompressed = new MemoryStream())
577 {
578 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
579 {
580 zOut.Write(input, 0, input.Length);
581 }
582
583 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
584 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
585 }
586
587 return osd;
588 }
589 }
590}
diff --git a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
index 70bda72..ba0b578 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.6.*")] 33[assembly: AssemblyVersion("0.8.0.*")]
34 34
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/ExtendedPhysics/ExtendedPhysics.cs b/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
index 6009dc5..9daf9d7 100755
--- a/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
@@ -29,12 +29,14 @@ using System.Collections.Generic;
29using System.Linq; 29using System.Linq;
30using System.Reflection; 30using System.Reflection;
31using System.Text; 31using System.Text;
32using System.Threading;
32 33
33using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.CoreModules;
34using OpenSim.Region.Framework; 36using OpenSim.Region.Framework;
35using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.CoreModules; 39using OpenSim.Region.Physics.Manager;
38 40
39using Mono.Addins; 41using Mono.Addins;
40using Nini.Config; 42using Nini.Config;
@@ -49,6 +51,24 @@ public class ExtendedPhysics : INonSharedRegionModule
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 private static string LogHeader = "[EXTENDED PHYSICS]"; 52 private static string LogHeader = "[EXTENDED PHYSICS]";
51 53
54 // =============================================================
55 // Since BulletSim is a plugin, this these values aren't defined easily in one place.
56 // This table must correspond to an identical table in BSScene.
57
58 // Per scene functions. See BSScene.
59
60 // Per avatar functions. See BSCharacter.
61
62 // Per prim functions. See BSPrim.
63 public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType";
64 public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
65 public const string PhysFunctChangeLinkFixed = "BulletSim.ChangeLinkFixed";
66 public const string PhysFunctChangeLinkType = "BulletSim.ChangeLinkType";
67 public const string PhysFunctGetLinkType = "BulletSim.GetLinkType";
68 public const string PhysFunctChangeLinkParams = "BulletSim.ChangeLinkParams";
69
70 // =============================================================
71
52 private IConfig Configuration { get; set; } 72 private IConfig Configuration { get; set; }
53 private bool Enabled { get; set; } 73 private bool Enabled { get; set; }
54 private Scene BaseScene { get; set; } 74 private Scene BaseScene { get; set; }
@@ -119,6 +139,7 @@ public class ExtendedPhysics : INonSharedRegionModule
119 139
120 // Register as LSL functions all the [ScriptInvocation] marked methods. 140 // Register as LSL functions all the [ScriptInvocation] marked methods.
121 Comms.RegisterScriptInvocations(this); 141 Comms.RegisterScriptInvocations(this);
142 Comms.RegisterConstants(this);
122 143
123 // When an object is modified, we might need to update its extended physics parameters 144 // When an object is modified, we might need to update its extended physics parameters
124 BaseScene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene; 145 BaseScene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
@@ -132,7 +153,6 @@ public class ExtendedPhysics : INonSharedRegionModule
132 153
133 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj) 154 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
134 { 155 {
135 throw new NotImplementedException();
136 } 156 }
137 157
138 // Event generated when some property of a prim changes. 158 // Event generated when some property of a prim changes.
@@ -141,14 +161,7 @@ public class ExtendedPhysics : INonSharedRegionModule
141 } 161 }
142 162
143 [ScriptConstant] 163 [ScriptConstant]
144 public static int PHYS_CENTER_OF_MASS = 1 << 0; 164 public const int PHYS_CENTER_OF_MASS = 1 << 0;
145
146 [ScriptConstant]
147 public static int PHYS_LINKSET_TYPE_CONSTRAINT = 1;
148 [ScriptConstant]
149 public static int PHYS_LINKSET_TYPE_COMPOUND = 2;
150 [ScriptConstant]
151 public static int PHYS_LINKSET_TYPE_MANUAL = 3;
152 165
153 [ScriptInvocation] 166 [ScriptInvocation]
154 public string physGetEngineType(UUID hostID, UUID scriptID) 167 public string physGetEngineType(UUID hostID, UUID scriptID)
@@ -163,9 +176,406 @@ public class ExtendedPhysics : INonSharedRegionModule
163 return ret; 176 return ret;
164 } 177 }
165 178
179 [ScriptConstant]
180 public const int PHYS_LINKSET_TYPE_CONSTRAINT = 0;
181 [ScriptConstant]
182 public const int PHYS_LINKSET_TYPE_COMPOUND = 1;
183 [ScriptConstant]
184 public const int PHYS_LINKSET_TYPE_MANUAL = 2;
185
186 [ScriptInvocation]
187 public int physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
188 {
189 int ret = -1;
190
191 if (!Enabled) return ret;
192
193 // The part that is requesting the change.
194 SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
195
196 if (requestingPart != null)
197 {
198 // The change is always made to the root of a linkset.
199 SceneObjectGroup containingGroup = requestingPart.ParentGroup;
200 SceneObjectPart rootPart = containingGroup.RootPart;
201
202 if (rootPart != null)
203 {
204 PhysicsActor rootPhysActor = rootPart.PhysActor;
205 if (rootPhysActor != null)
206 {
207 if (rootPhysActor.IsPhysical)
208 {
209 // Change a physical linkset by making non-physical, waiting for one heartbeat so all
210 // the prim and linkset state is updated, changing the type and making the
211 // linkset physical again.
212 containingGroup.ScriptSetPhysicsStatus(false);
213 Thread.Sleep(150); // longer than one heartbeat tick
214
215 // A kludge for the moment.
216 // Since compound linksets move the children but don't generate position updates to the
217 // simulator, it is possible for compound linkset children to have out-of-sync simulator
218 // and physical positions. The following causes the simulator to push the real child positions
219 // down into the physics engine to get everything synced.
220 containingGroup.UpdateGroupPosition(containingGroup.AbsolutePosition);
221 containingGroup.UpdateGroupRotationR(containingGroup.GroupRotation);
222
223 object[] parms2 = { rootPhysActor, null, linksetType };
224 ret = MakeIntError(rootPhysActor.Extension(PhysFunctSetLinksetType, parms2));
225 Thread.Sleep(150); // longer than one heartbeat tick
226
227 containingGroup.ScriptSetPhysicsStatus(true);
228 }
229 else
230 {
231 // Non-physical linksets don't have a physical instantiation so there is no state to
232 // worry about being updated.
233 object[] parms2 = { rootPhysActor, null, linksetType };
234 ret = MakeIntError(rootPhysActor.Extension(PhysFunctSetLinksetType, parms2));
235 }
236 }
237 else
238 {
239 m_log.WarnFormat("{0} physSetLinksetType: root part does not have a physics actor. rootName={1}, hostID={2}",
240 LogHeader, rootPart.Name, hostID);
241 }
242 }
243 else
244 {
245 m_log.WarnFormat("{0} physSetLinksetType: root part does not exist. RequestingPartName={1}, hostID={2}",
246 LogHeader, requestingPart.Name, hostID);
247 }
248 }
249 else
250 {
251 m_log.WarnFormat("{0} physSetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID);
252 }
253 return ret;
254 }
255
166 [ScriptInvocation] 256 [ScriptInvocation]
167 public void physSetLinksetType(UUID hostID, UUID scriptID, int linksetType) 257 public int physGetLinksetType(UUID hostID, UUID scriptID)
168 { 258 {
259 int ret = -1;
260 if (!Enabled) return ret;
261
262 // The part that is requesting the change.
263 SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
264
265 if (requestingPart != null)
266 {
267 // The type is is always on the root of a linkset.
268 SceneObjectGroup containingGroup = requestingPart.ParentGroup;
269 SceneObjectPart rootPart = containingGroup.RootPart;
270
271 if (rootPart != null)
272 {
273 PhysicsActor rootPhysActor = rootPart.PhysActor;
274 if (rootPhysActor != null)
275 {
276 object[] parms2 = { rootPhysActor, null };
277 ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinksetType, parms2));
278 }
279 else
280 {
281 m_log.WarnFormat("{0} physGetLinksetType: root part does not have a physics actor. rootName={1}, hostID={2}",
282 LogHeader, rootPart.Name, hostID);
283 }
284 }
285 else
286 {
287 m_log.WarnFormat("{0} physGetLinksetType: root part does not exist. RequestingPartName={1}, hostID={2}",
288 LogHeader, requestingPart.Name, hostID);
289 }
290 }
291 else
292 {
293 m_log.WarnFormat("{0} physGetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID);
294 }
295 return ret;
296 }
297
298 [ScriptConstant]
299 public const int PHYS_LINK_TYPE_FIXED = 1234;
300 [ScriptConstant]
301 public const int PHYS_LINK_TYPE_HINGE = 4;
302 [ScriptConstant]
303 public const int PHYS_LINK_TYPE_SPRING = 9;
304 [ScriptConstant]
305 public const int PHYS_LINK_TYPE_6DOF = 6;
306 [ScriptConstant]
307 public const int PHYS_LINK_TYPE_SLIDER = 7;
308
309 // physChangeLinkType(integer linkNum, integer typeCode)
310 [ScriptInvocation]
311 public int physChangeLinkType(UUID hostID, UUID scriptID, int linkNum, int typeCode)
312 {
313 int ret = -1;
314 if (!Enabled) return ret;
315
316 PhysicsActor rootPhysActor;
317 PhysicsActor childPhysActor;
318
319 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
320 {
321 object[] parms2 = { rootPhysActor, childPhysActor, typeCode };
322 ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkType, parms2));
323 }
324
325 return ret;
326 }
327
328 // physGetLinkType(integer linkNum)
329 [ScriptInvocation]
330 public int physGetLinkType(UUID hostID, UUID scriptID, int linkNum)
331 {
332 int ret = -1;
333 if (!Enabled) return ret;
334
335 PhysicsActor rootPhysActor;
336 PhysicsActor childPhysActor;
337
338 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
339 {
340 object[] parms2 = { rootPhysActor, childPhysActor };
341 ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinkType, parms2));
342 }
343
344 return ret;
345 }
346
347 // physChangeLinkFixed(integer linkNum)
348 // Change the link between the root and the linkNum into a fixed, static physical connection.
349 [ScriptInvocation]
350 public int physChangeLinkFixed(UUID hostID, UUID scriptID, int linkNum)
351 {
352 int ret = -1;
353 if (!Enabled) return ret;
354
355 PhysicsActor rootPhysActor;
356 PhysicsActor childPhysActor;
357
358 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
359 {
360 object[] parms2 = { rootPhysActor, childPhysActor , PHYS_LINK_TYPE_FIXED };
361 ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkType, parms2));
362 }
363
364 return ret;
365 }
366
367 // Code for specifying params.
368 // The choice if 14400 is arbitrary and only serves to catch parameter code misuse.
369 public const int PHYS_PARAM_MIN = 14401;
370
371 [ScriptConstant]
372 public const int PHYS_PARAM_FRAMEINA_LOC = 14401;
373 [ScriptConstant]
374 public const int PHYS_PARAM_FRAMEINA_ROT = 14402;
375 [ScriptConstant]
376 public const int PHYS_PARAM_FRAMEINB_LOC = 14403;
377 [ScriptConstant]
378 public const int PHYS_PARAM_FRAMEINB_ROT = 14404;
379 [ScriptConstant]
380 public const int PHYS_PARAM_LINEAR_LIMIT_LOW = 14405;
381 [ScriptConstant]
382 public const int PHYS_PARAM_LINEAR_LIMIT_HIGH = 14406;
383 [ScriptConstant]
384 public const int PHYS_PARAM_ANGULAR_LIMIT_LOW = 14407;
385 [ScriptConstant]
386 public const int PHYS_PARAM_ANGULAR_LIMIT_HIGH = 14408;
387 [ScriptConstant]
388 public const int PHYS_PARAM_USE_FRAME_OFFSET = 14409;
389 [ScriptConstant]
390 public const int PHYS_PARAM_ENABLE_TRANSMOTOR = 14410;
391 [ScriptConstant]
392 public const int PHYS_PARAM_TRANSMOTOR_MAXVEL = 14411;
393 [ScriptConstant]
394 public const int PHYS_PARAM_TRANSMOTOR_MAXFORCE = 14412;
395 [ScriptConstant]
396 public const int PHYS_PARAM_CFM = 14413;
397 [ScriptConstant]
398 public const int PHYS_PARAM_ERP = 14414;
399 [ScriptConstant]
400 public const int PHYS_PARAM_SOLVER_ITERATIONS = 14415;
401 [ScriptConstant]
402 public const int PHYS_PARAM_SPRING_AXIS_ENABLE = 14416;
403 [ScriptConstant]
404 public const int PHYS_PARAM_SPRING_DAMPING = 14417;
405 [ScriptConstant]
406 public const int PHYS_PARAM_SPRING_STIFFNESS = 14418;
407 [ScriptConstant]
408 public const int PHYS_PARAM_LINK_TYPE = 14419;
409 [ScriptConstant]
410 public const int PHYS_PARAM_USE_LINEAR_FRAMEA = 14420;
411 [ScriptConstant]
412 public const int PHYS_PARAM_SPRING_EQUILIBRIUM_POINT = 14421;
413
414 public const int PHYS_PARAM_MAX = 14421;
415
416 // Used when specifying a parameter that has settings for the three linear and three angular axis
417 [ScriptConstant]
418 public const int PHYS_AXIS_ALL = -1;
419 [ScriptConstant]
420 public const int PHYS_AXIS_LINEAR_ALL = -2;
421 [ScriptConstant]
422 public const int PHYS_AXIS_ANGULAR_ALL = -3;
423 [ScriptConstant]
424 public const int PHYS_AXIS_LINEAR_X = 0;
425 [ScriptConstant]
426 public const int PHYS_AXIS_LINEAR_Y = 1;
427 [ScriptConstant]
428 public const int PHYS_AXIS_LINEAR_Z = 2;
429 [ScriptConstant]
430 public const int PHYS_AXIS_ANGULAR_X = 3;
431 [ScriptConstant]
432 public const int PHYS_AXIS_ANGULAR_Y = 4;
433 [ScriptConstant]
434 public const int PHYS_AXIS_ANGULAR_Z = 5;
435
436 // physChangeLinkParams(integer linkNum, [ PHYS_PARAM_*, value, PHYS_PARAM_*, value, ...])
437 [ScriptInvocation]
438 public int physChangeLinkParams(UUID hostID, UUID scriptID, int linkNum, object[] parms)
439 {
440 int ret = -1;
441 if (!Enabled) return ret;
442
443 PhysicsActor rootPhysActor;
444 PhysicsActor childPhysActor;
445
446 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
447 {
448 object[] parms2 = AddToBeginningOfArray(rootPhysActor, childPhysActor, parms);
449 ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkParams, parms2));
450 }
451
452 return ret;
453 }
454
455 private bool GetRootPhysActor(UUID hostID, out PhysicsActor rootPhysActor)
456 {
457 SceneObjectGroup containingGroup;
458 SceneObjectPart rootPart;
459 return GetRootPhysActor(hostID, out containingGroup, out rootPart, out rootPhysActor);
460 }
461
462 private bool GetRootPhysActor(UUID hostID, out SceneObjectGroup containingGroup, out SceneObjectPart rootPart, out PhysicsActor rootPhysActor)
463 {
464 bool ret = false;
465 rootPhysActor = null;
466 containingGroup = null;
467 rootPart = null;
468
469 SceneObjectPart requestingPart;
470
471 requestingPart = BaseScene.GetSceneObjectPart(hostID);
472 if (requestingPart != null)
473 {
474 // The type is is always on the root of a linkset.
475 containingGroup = requestingPart.ParentGroup;
476 if (containingGroup != null && !containingGroup.IsDeleted)
477 {
478 rootPart = containingGroup.RootPart;
479 if (rootPart != null)
480 {
481 rootPhysActor = rootPart.PhysActor;
482 if (rootPhysActor != null)
483 {
484 ret = true;
485 }
486 else
487 {
488 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not have a physics actor. rootName={1}, hostID={2}",
489 LogHeader, rootPart.Name, hostID);
490 }
491 }
492 else
493 {
494 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not exist. RequestingPartName={1}, hostID={2}",
495 LogHeader, requestingPart.Name, hostID);
496 }
497 }
498 else
499 {
500 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Containing group missing or deleted. hostID={1}", LogHeader, hostID);
501 }
502 }
503 else
504 {
505 m_log.WarnFormat("{0} GetRootAndChildPhysActors: cannot find script object in scene. hostID={1}", LogHeader, hostID);
506 }
507
508 return ret;
509 }
510
511 // Find the root and child PhysActors based on the linkNum.
512 // Return 'true' if both are found and returned.
513 private bool GetRootAndChildPhysActors(UUID hostID, int linkNum, out PhysicsActor rootPhysActor, out PhysicsActor childPhysActor)
514 {
515 bool ret = false;
516 rootPhysActor = null;
517 childPhysActor = null;
518
519 SceneObjectGroup containingGroup;
520 SceneObjectPart rootPart;
521
522 if (GetRootPhysActor(hostID, out containingGroup, out rootPart, out rootPhysActor))
523 {
524 SceneObjectPart linkPart = containingGroup.GetLinkNumPart(linkNum);
525 if (linkPart != null)
526 {
527 childPhysActor = linkPart.PhysActor;
528 if (childPhysActor != null)
529 {
530 ret = true;
531 }
532 else
533 {
534 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Link part has no physical actor. rootName={1}, hostID={2}, linknum={3}",
535 LogHeader, rootPart.Name, hostID, linkNum);
536 }
537 }
538 else
539 {
540 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Could not find linknum part. rootName={1}, hostID={2}, linknum={3}",
541 LogHeader, rootPart.Name, hostID, linkNum);
542 }
543 }
544 else
545 {
546 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not have a physics actor. rootName={1}, hostID={2}",
547 LogHeader, rootPart.Name, hostID);
548 }
549
550 return ret;
551 }
552
553 // Return an array of objects with the passed object as the first object of a new array
554 private object[] AddToBeginningOfArray(object firstOne, object secondOne, object[] prevArray)
555 {
556 object[] newArray = new object[2 + prevArray.Length];
557 newArray[0] = firstOne;
558 newArray[1] = secondOne;
559 prevArray.CopyTo(newArray, 2);
560 return newArray;
561 }
562
563 // Extension() returns an object. Convert that object into the integer error we expect to return.
564 private int MakeIntError(object extensionRet)
565 {
566 int ret = -1;
567 if (extensionRet != null)
568 {
569 try
570 {
571 ret = (int)extensionRet;
572 }
573 catch
574 {
575 ret = -1;
576 }
577 }
578 return ret;
169 } 579 }
170} 580}
171} 581}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs
new file mode 100644
index 0000000..d4b19dd
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs
@@ -0,0 +1,195 @@
1/*
2 * Copyright (c) Contributors
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 OpenSim 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 Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreCommandsModule")]
48
49 public class JsonStoreCommandsModule : INonSharedRegionModule
50 {
51 private static readonly ILog m_log =
52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private IConfig m_config = null;
55 private bool m_enabled = false;
56
57 private Scene m_scene = null;
58 //private IJsonStoreModule m_store;
59 private JsonStoreModule m_store;
60
61#region Region Module interface
62
63 // -----------------------------------------------------------------
64 /// <summary>
65 /// Name of this shared module is it's class name
66 /// </summary>
67 // -----------------------------------------------------------------
68 public string Name
69 {
70 get { return this.GetType().Name; }
71 }
72
73 // -----------------------------------------------------------------
74 /// <summary>
75 /// Initialise this shared module
76 /// </summary>
77 /// <param name="scene">this region is getting initialised</param>
78 /// <param name="source">nini config, we are not using this</param>
79 // -----------------------------------------------------------------
80 public void Initialise(IConfigSource config)
81 {
82 try
83 {
84 if ((m_config = config.Configs["JsonStore"]) == null)
85 {
86 // There is no configuration, the module is disabled
87 // m_log.InfoFormat("[JsonStore] no configuration info");
88 return;
89 }
90
91 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
92 }
93 catch (Exception e)
94 {
95 m_log.Error("[JsonStore]: initialization error: {0}", e);
96 return;
97 }
98
99 if (m_enabled)
100 m_log.DebugFormat("[JsonStore]: module is enabled");
101 }
102
103 // -----------------------------------------------------------------
104 /// <summary>
105 /// everything is loaded, perform post load configuration
106 /// </summary>
107 // -----------------------------------------------------------------
108 public void PostInitialise()
109 {
110 }
111
112 // -----------------------------------------------------------------
113 /// <summary>
114 /// Nothing to do on close
115 /// </summary>
116 // -----------------------------------------------------------------
117 public void Close()
118 {
119 }
120
121 // -----------------------------------------------------------------
122 /// <summary>
123 /// </summary>
124 // -----------------------------------------------------------------
125 public void AddRegion(Scene scene)
126 {
127 if (m_enabled)
128 {
129 m_scene = scene;
130
131 }
132 }
133
134 // -----------------------------------------------------------------
135 /// <summary>
136 /// </summary>
137 // -----------------------------------------------------------------
138 public void RemoveRegion(Scene scene)
139 {
140 // need to remove all references to the scene in the subscription
141 // list to enable full garbage collection of the scene object
142 }
143
144 // -----------------------------------------------------------------
145 /// <summary>
146 /// Called when all modules have been added for a region. This is
147 /// where we hook up events
148 /// </summary>
149 // -----------------------------------------------------------------
150 public void RegionLoaded(Scene scene)
151 {
152 if (m_enabled)
153 {
154 m_scene = scene;
155
156 m_store = (JsonStoreModule) m_scene.RequestModuleInterface<IJsonStoreModule>();
157 if (m_store == null)
158 {
159 m_log.ErrorFormat("[JsonStoreCommands]: JsonModule interface not defined");
160 m_enabled = false;
161 return;
162 }
163
164 scene.AddCommand("JsonStore", this, "jsonstore stats", "jsonstore stats",
165 "Display statistics about the state of the JsonStore module", "",
166 CmdStats);
167 }
168 }
169
170 /// -----------------------------------------------------------------
171 /// <summary>
172 /// </summary>
173 // -----------------------------------------------------------------
174 public Type ReplaceableInterface
175 {
176 get { return null; }
177 }
178
179#endregion
180
181#region Commands
182
183 private void CmdStats(string module, string[] cmd)
184 {
185 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
186 return;
187
188 JsonStoreStats stats = m_store.GetStoreStats();
189 MainConsole.Instance.OutputFormat("{0}\t{1}",m_scene.RegionInfo.RegionName,stats.StoreCount);
190 }
191
192#endregion
193
194 }
195}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
index 5fbfcc5..b502a55 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -42,7 +42,6 @@ using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic; 42using System.Collections.Generic;
43using System.Text.RegularExpressions; 43using System.Text.RegularExpressions;
44 44
45
46namespace OpenSim.Region.OptionalModules.Scripting.JsonStore 45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
47{ 46{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")] 47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")]
@@ -60,6 +59,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
60 private Scene m_scene = null; 59 private Scene m_scene = null;
61 60
62 private Dictionary<UUID,JsonStore> m_JsonValueStore; 61 private Dictionary<UUID,JsonStore> m_JsonValueStore;
62
63 private UUID m_sharedStore; 63 private UUID m_sharedStore;
64 64
65#region Region Module interface 65#region Region Module interface
@@ -140,6 +140,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
140 m_sharedStore = UUID.Zero; 140 m_sharedStore = UUID.Zero;
141 m_JsonValueStore = new Dictionary<UUID,JsonStore>(); 141 m_JsonValueStore = new Dictionary<UUID,JsonStore>();
142 m_JsonValueStore.Add(m_sharedStore,new JsonStore("")); 142 m_JsonValueStore.Add(m_sharedStore,new JsonStore(""));
143
144 scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene;
143 } 145 }
144 } 146 }
145 147
@@ -149,6 +151,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
149 // ----------------------------------------------------------------- 151 // -----------------------------------------------------------------
150 public void RemoveRegion(Scene scene) 152 public void RemoveRegion(Scene scene)
151 { 153 {
154 scene.EventManager.OnObjectBeingRemovedFromScene -= EventManagerOnObjectBeingRemovedFromScene;
155
152 // need to remove all references to the scene in the subscription 156 // need to remove all references to the scene in the subscription
153 // list to enable full garbage collection of the scene object 157 // list to enable full garbage collection of the scene object
154 } 158 }
@@ -161,7 +165,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
161 // ----------------------------------------------------------------- 165 // -----------------------------------------------------------------
162 public void RegionLoaded(Scene scene) 166 public void RegionLoaded(Scene scene)
163 { 167 {
164 if (m_enabled) {} 168 if (m_enabled)
169 {
170 }
165 } 171 }
166 172
167 /// ----------------------------------------------------------------- 173 /// -----------------------------------------------------------------
@@ -175,8 +181,39 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
175 181
176#endregion 182#endregion
177 183
184#region SceneEvents
185 // -----------------------------------------------------------------
186 /// <summary>
187 ///
188 /// </summary>
189 // -----------------------------------------------------------------
190 public void EventManagerOnObjectBeingRemovedFromScene(SceneObjectGroup obj)
191 {
192 obj.ForEachPart(delegate(SceneObjectPart sop) { DestroyStore(sop.UUID); } );
193 }
194
195#endregion
196
178#region ScriptInvocationInteface 197#region ScriptInvocationInteface
179 198
199
200 // -----------------------------------------------------------------
201 /// <summary>
202 ///
203 /// </summary>
204 // -----------------------------------------------------------------
205 public JsonStoreStats GetStoreStats()
206 {
207 JsonStoreStats stats;
208
209 lock (m_JsonValueStore)
210 {
211 stats.StoreCount = m_JsonValueStore.Count;
212 }
213
214 return stats;
215 }
216
180 // ----------------------------------------------------------------- 217 // -----------------------------------------------------------------
181 /// <summary> 218 /// <summary>
182 /// 219 ///
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
index 1bb5aee..9fbfb66 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -59,7 +59,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
59 59
60 private IScriptModuleComms m_comms; 60 private IScriptModuleComms m_comms;
61 private IJsonStoreModule m_store; 61 private IJsonStoreModule m_store;
62 62
63 private Dictionary<UUID,HashSet<UUID>> m_scriptStores = new Dictionary<UUID,HashSet<UUID>>();
64
63#region Region Module interface 65#region Region Module interface
64 66
65 // ----------------------------------------------------------------- 67 // -----------------------------------------------------------------
@@ -126,6 +128,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
126 // ----------------------------------------------------------------- 128 // -----------------------------------------------------------------
127 public void AddRegion(Scene scene) 129 public void AddRegion(Scene scene)
128 { 130 {
131 scene.EventManager.OnScriptReset += HandleScriptReset;
132 scene.EventManager.OnRemoveScript += HandleScriptReset;
129 } 133 }
130 134
131 // ----------------------------------------------------------------- 135 // -----------------------------------------------------------------
@@ -134,12 +138,34 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
134 // ----------------------------------------------------------------- 138 // -----------------------------------------------------------------
135 public void RemoveRegion(Scene scene) 139 public void RemoveRegion(Scene scene)
136 { 140 {
141 scene.EventManager.OnScriptReset -= HandleScriptReset;
142 scene.EventManager.OnRemoveScript -= HandleScriptReset;
143
137 // need to remove all references to the scene in the subscription 144 // need to remove all references to the scene in the subscription
138 // list to enable full garbage collection of the scene object 145 // list to enable full garbage collection of the scene object
139 } 146 }
140 147
141 // ----------------------------------------------------------------- 148 // -----------------------------------------------------------------
142 /// <summary> 149 /// <summary>
150 /// </summary>
151 // -----------------------------------------------------------------
152 private void HandleScriptReset(uint localID, UUID itemID)
153 {
154 HashSet<UUID> stores;
155
156 lock (m_scriptStores)
157 {
158 if (! m_scriptStores.TryGetValue(itemID, out stores))
159 return;
160 m_scriptStores.Remove(itemID);
161 }
162
163 foreach (UUID id in stores)
164 m_store.DestroyStore(id);
165 }
166
167 // -----------------------------------------------------------------
168 /// <summary>
143 /// Called when all modules have been added for a region. This is 169 /// Called when all modules have been added for a region. This is
144 /// where we hook up events 170 /// where we hook up events
145 /// </summary> 171 /// </summary>
@@ -250,6 +276,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
250 if (! m_store.CreateStore(value, ref uuid)) 276 if (! m_store.CreateStore(value, ref uuid))
251 GenerateRuntimeError("Failed to create Json store"); 277 GenerateRuntimeError("Failed to create Json store");
252 278
279 lock (m_scriptStores)
280 {
281 if (! m_scriptStores.ContainsKey(scriptID))
282 m_scriptStores[scriptID] = new HashSet<UUID>();
283
284 m_scriptStores[scriptID].Add(uuid);
285 }
253 return uuid; 286 return uuid;
254 } 287 }
255 288
@@ -261,6 +294,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
261 [ScriptInvocation] 294 [ScriptInvocation]
262 public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID) 295 public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID)
263 { 296 {
297 lock(m_scriptStores)
298 {
299 if (m_scriptStores.ContainsKey(scriptID))
300 m_scriptStores[scriptID].Remove(storeID);
301 }
302
264 return m_store.DestroyStore(storeID) ? 1 : 0; 303 return m_store.DestroyStore(storeID) ? 1 : 0;
265 } 304 }
266 305
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index c550c44..eb386fe 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -105,7 +105,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
105 m_scene.LoginLock = true; 105 m_scene.LoginLock = true;
106 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; 106 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
107 107
108 m_log.InfoFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name); 108 // Warn level because the region cannot be used while logins are disabled
109 m_log.WarnFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name);
109 110
110 if (m_uri != string.Empty) 111 if (m_uri != string.Empty)
111 { 112 {
@@ -215,8 +216,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
215 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", 216 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}",
216 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); 217 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString());
217 218
218 m_log.InfoFormat( 219 // Putting this out to console to make it eye-catching for people who are running OpenSimulator
219 "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); 220 // without info log messages enabled. Making this a warning is arguably misleading since it isn't a
221 // warning, and monitor scripts looking for warn/error/fatal messages will received false positives.
222 // Arguably, log4net needs a status log level (like Apache).
223 MainConsole.Instance.OutputFormat("INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name);
220 } 224 }
221 225
222 m_scene.SceneGridService.InformNeighborsThatRegionisUp( 226 m_scene.SceneGridService.InformNeighborsThatRegionisUp(
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
index c68fe99..3b3b300 100644
--- a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
@@ -263,7 +263,7 @@ namespace OpenSim.Region.OptionalModules.ViewerSupport
263 m_module = module; 263 m_module = module;
264 } 264 }
265 265
266 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 266 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
267 { 267 {
268 StreamReader reader = new StreamReader(request); 268 StreamReader reader = new StreamReader(request);
269 string requestBody = reader.ReadToEnd(); 269 string requestBody = reader.ReadToEnd();
diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
index 5d10e93..bcb21d0 100644
--- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
+++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
@@ -696,7 +696,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
696 /// <param name="agentId"></param> 696 /// <param name="agentId"></param>
697 public void EconomyDataRequestHandler(IClientAPI user) 697 public void EconomyDataRequestHandler(IClientAPI user)
698 { 698 {
699 Scene s = LocateSceneClientIn(user.AgentId); 699 Scene s = (Scene)user.Scene;
700 700
701 user.SendEconomyData(EnergyEfficiency, s.RegionInfo.ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate, 701 user.SendEconomyData(EnergyEfficiency, s.RegionInfo.ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate,
702 PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor, 702 PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor,
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 4674489..c88ccc5 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -44,6 +44,20 @@ namespace OpenSim.Region.OptionalModules.World.NPC
44 { 44 {
45 public bool SenseAsAgent { get; set; } 45 public bool SenseAsAgent { get; set; }
46 46
47 public delegate void ChatToNPC(
48 string message, byte type, Vector3 fromPos, string fromName,
49 UUID fromAgentID, UUID ownerID, byte source, byte audible);
50
51 /// <summary>
52 /// Fired when the NPC receives a chat message.
53 /// </summary>
54 public event ChatToNPC OnChatToNPC;
55
56 /// <summary>
57 /// Fired when the NPC receives an instant message.
58 /// </summary>
59 public event Action<GridInstantMessage> OnInstantMessageToNPC;
60
47 private readonly string m_firstname; 61 private readonly string m_firstname;
48 private readonly string m_lastname; 62 private readonly string m_lastname;
49 private readonly Vector3 m_startPos; 63 private readonly Vector3 m_startPos;
@@ -259,6 +273,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
259 public event Action<IClientAPI, bool> OnCompleteMovementToRegion; 273 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
260 public event UpdateAgent OnPreAgentUpdate; 274 public event UpdateAgent OnPreAgentUpdate;
261 public event UpdateAgent OnAgentUpdate; 275 public event UpdateAgent OnAgentUpdate;
276 public event UpdateAgent OnAgentCameraUpdate;
262 public event AgentRequestSit OnAgentRequestSit; 277 public event AgentRequestSit OnAgentRequestSit;
263 public event AgentSit OnAgentSit; 278 public event AgentSit OnAgentSit;
264 public event AvatarPickerRequest OnAvatarPickerRequest; 279 public event AvatarPickerRequest OnAvatarPickerRequest;
@@ -393,6 +408,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
393 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest; 408 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
394 public event EstateChangeInfo OnEstateChangeInfo; 409 public event EstateChangeInfo OnEstateChangeInfo;
395 public event EstateManageTelehub OnEstateManageTelehub; 410 public event EstateManageTelehub OnEstateManageTelehub;
411 public event CachedTextureRequest OnCachedTextureRequest;
396 public event ScriptReset OnScriptReset; 412 public event ScriptReset OnScriptReset;
397 public event GetScriptRunning OnGetScriptRunning; 413 public event GetScriptRunning OnGetScriptRunning;
398 public event SetScriptRunning OnSetScriptRunning; 414 public event SetScriptRunning OnSetScriptRunning;
@@ -573,6 +589,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
573 { 589 {
574 } 590 }
575 591
592 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
593 {
594
595 }
596
576 public virtual void Kick(string message) 597 public virtual void Kick(string message)
577 { 598 {
578 } 599 }
@@ -590,7 +611,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
590 611
591 } 612 }
592 613
593 public virtual void SendKillObject(ulong regionHandle, List<uint> localID) 614 public virtual void SendKillObject(List<uint> localID)
594 { 615 {
595 } 616 }
596 617
@@ -617,17 +638,18 @@ namespace OpenSim.Region.OptionalModules.World.NPC
617 string message, byte type, Vector3 fromPos, string fromName, 638 string message, byte type, Vector3 fromPos, string fromName,
618 UUID fromAgentID, UUID ownerID, byte source, byte audible) 639 UUID fromAgentID, UUID ownerID, byte source, byte audible)
619 { 640 {
620 } 641 ChatToNPC ctn = OnChatToNPC;
621 642
622 public virtual void SendChatMessage( 643 if (ctn != null)
623 byte[] message, byte type, Vector3 fromPos, string fromName, 644 ctn(message, type, fromPos, fromName, fromAgentID, ownerID, source, audible);
624 UUID fromAgentID, UUID ownerID, byte source, byte audible)
625 {
626 } 645 }
627 646
628 public void SendInstantMessage(GridInstantMessage im) 647 public void SendInstantMessage(GridInstantMessage im)
629 { 648 {
630 649 Action<GridInstantMessage> oimtn = OnInstantMessageToNPC;
650
651 if (oimtn != null)
652 oimtn(im);
631 } 653 }
632 654
633 public void SendGenericMessage(string method, UUID invoice, List<string> message) 655 public void SendGenericMessage(string method, UUID invoice, List<string> message)
@@ -1236,7 +1258,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
1236 { 1258 {
1237 } 1259 }
1238 1260
1239 public void StopFlying(ISceneEntity presence) 1261 public void SendAgentTerseUpdate(ISceneEntity presence)
1240 { 1262 {
1241 } 1263 }
1242 1264
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 8c9c006..9ec4740 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -116,7 +116,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
116 return false; 116 return false;
117 117
118 // Delete existing npc attachments 118 // Delete existing npc attachments
119 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false); 119 if(scene.AttachmentsModule != null)
120 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false);
120 121
121 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet 122 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet
122 // since it doesn't transfer attachments 123 // since it doesn't transfer attachments
@@ -125,7 +126,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
125 npc.Appearance = npcAppearance; 126 npc.Appearance = npcAppearance;
126 127
127 // Rez needed npc attachments 128 // Rez needed npc attachments
128 scene.AttachmentsModule.RezAttachments(npc); 129 if (scene.AttachmentsModule != null)
130 scene.AttachmentsModule.RezAttachments(npc);
129 131
130 IAvatarFactoryModule module = 132 IAvatarFactoryModule module =
131 scene.RequestModuleInterface<IAvatarFactoryModule>(); 133 scene.RequestModuleInterface<IAvatarFactoryModule>();
@@ -174,7 +176,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
174 lock (m_avatars) 176 lock (m_avatars)
175 { 177 {
176 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd); 178 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
177 scene.AddNewClient(npcAvatar, PresenceType.Npc); 179 scene.AddNewAgent(npcAvatar, PresenceType.Npc);
178 180
179 ScenePresence sp; 181 ScenePresence sp;
180 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) 182 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
@@ -205,8 +207,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
205 if (scene.TryGetScenePresence(agentID, out sp)) 207 if (scene.TryGetScenePresence(agentID, out sp))
206 { 208 {
207// m_log.DebugFormat( 209// m_log.DebugFormat(
208// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}", 210// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
209// sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget); 211// sp.Name, pos, scene.RegionInfo.RegionName,
212// noFly, landAtTarget);
210 213
211 sp.MoveToTarget(pos, noFly, landAtTarget); 214 sp.MoveToTarget(pos, noFly, landAtTarget);
212 sp.SetAlwaysRun = running; 215 sp.SetAlwaysRun = running;
@@ -283,9 +286,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
283 ScenePresence sp; 286 ScenePresence sp;
284 if (scene.TryGetScenePresence(agentID, out sp)) 287 if (scene.TryGetScenePresence(agentID, out sp))
285 { 288 {
286 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, 289 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
287 partID, Vector3.Zero);
288 //sp.HandleAgentSit(m_avatars[agentID], agentID);
289 290
290 return true; 291 return true;
291 } 292 }
@@ -375,10 +376,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
375 m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove", 376 m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove",
376 agentID, av.Name); 377 agentID, av.Name);
377 */ 378 */
378 scene.RemoveClient(agentID, false); 379
380 scene.CloseAgent(agentID, false);
381
379 m_avatars.Remove(agentID); 382 m_avatars.Remove(agentID);
380 383
381// m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}", agentID, av.Name); 384 /*
385 m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}",
386 agentID, av.Name);
387 */
382 return true; 388 return true;
383 } 389 }
384 } 390 }
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 34362af..14eb25b 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -155,7 +155,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
155 public void TestCreateWithAttachments() 155 public void TestCreateWithAttachments()
156 { 156 {
157 TestHelpers.InMethod(); 157 TestHelpers.InMethod();
158// log4net.Config.XmlConfigurator.Configure(); 158// TestHelpers.EnableLogging();
159 159
160 UUID userId = TestHelpers.ParseTail(0x1); 160 UUID userId = TestHelpers.ParseTail(0x1);
161 UserAccountHelpers.CreateUserWithInventory(m_scene, userId); 161 UserAccountHelpers.CreateUserWithInventory(m_scene, userId);
@@ -321,9 +321,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
321 321
322 Assert.That(part.SitTargetAvatar, Is.EqualTo(npcId)); 322 Assert.That(part.SitTargetAvatar, Is.EqualTo(npcId));
323 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); 323 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId));
324 Assert.That( 324// Assert.That(
325 npc.AbsolutePosition, 325// npc.AbsolutePosition,
326 Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); 326// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
327 327
328 m_npcMod.Stand(npc.UUID, m_scene); 328 m_npcMod.Stand(npc.UUID, m_scene);
329 329
@@ -335,7 +335,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
335 public void TestSitAndStandWithNoSitTarget() 335 public void TestSitAndStandWithNoSitTarget()
336 { 336 {
337 TestHelpers.InMethod(); 337 TestHelpers.InMethod();
338// log4net.Config.XmlConfigurator.Configure(); 338// TestHelpers.EnableLogging();
339 339
340 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); 340 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
341 341
@@ -353,13 +353,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
353 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); 353 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
354 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); 354 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId));
355 355
356 // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the 356 // We should really be using the NPC size but this would mean preserving the physics actor since it is
357 // default avatar. 357 // removed on sit.
358 // Curiously, Vector3.ToString() will not display the last two places of the float. For example,
359 // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337>
360 Assert.That( 358 Assert.That(
361 npc.AbsolutePosition, 359 npc.AbsolutePosition,
362 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, 0.845499337f))); 360 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, sp.PhysicsActor.Size.Z / 2)));
363 361
364 m_npcMod.Stand(npc.UUID, m_scene); 362 m_npcMod.Stand(npc.UUID, m_scene);
365 363
diff --git a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs
index 550b5d4..8720cc7 100644
--- a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs
+++ b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.OptionalModules.World.WorldView
55 m_WorldViewModule = fmodule; 55 m_WorldViewModule = fmodule;
56 } 56 }
57 57
58 public override byte[] Handle(string path, Stream requestData, 58 protected override byte[] ProcessRequest(string path, Stream requestData,
59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
60 { 60 {
61 httpResponse.ContentType = "image/jpeg"; 61 httpResponse.ContentType = "image/jpeg";
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
index 6fd6f7e..ffcb01e 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.6.*")] 58[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
index e43136a..0d17e0e 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
@@ -118,14 +118,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
118 118
119 public override Vector3 Position { get; set; } 119 public override Vector3 Position { get; set; }
120 120
121 public override Vector3 Size 121 public override Vector3 Size { get; set; }
122 {
123 get { return _size; }
124 set {
125 _size = value;
126 _size.Z = _size.Z / 2.0f;
127 }
128 }
129 122
130 public override PrimitiveBaseShape Shape 123 public override PrimitiveBaseShape Shape
131 { 124 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index f5b84d4..3bd81d4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -75,11 +75,11 @@ private sealed class BulletBodyUnman : BulletBody
75private sealed class BulletShapeUnman : BulletShape 75private sealed class BulletShapeUnman : BulletShape
76{ 76{
77 public IntPtr ptr; 77 public IntPtr ptr;
78 public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ) 78 public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ)
79 : base() 79 : base()
80 { 80 {
81 ptr = xx; 81 ptr = xx;
82 type = typ; 82 shapeType = typ;
83 } 83 }
84 public override bool HasPhysicalShape 84 public override bool HasPhysicalShape
85 { 85 {
@@ -91,7 +91,7 @@ private sealed class BulletShapeUnman : BulletShape
91 } 91 }
92 public override BulletShape Clone() 92 public override BulletShape Clone()
93 { 93 {
94 return new BulletShapeUnman(ptr, type); 94 return new BulletShapeUnman(ptr, shapeType);
95 } 95 }
96 public override bool ReferenceSame(BulletShape other) 96 public override bool ReferenceSame(BulletShape other)
97 { 97 {
@@ -251,11 +251,21 @@ public override BulletShape CreateMeshShape(BulletWorld world,
251 BSPhysicsShapeType.SHAPE_MESH); 251 BSPhysicsShapeType.SHAPE_MESH);
252} 252}
253 253
254public override BulletShape CreateGImpactShape(BulletWorld world,
255 int indicesCount, int[] indices,
256 int verticesCount, float[] vertices)
257{
258 BulletWorldUnman worldu = world as BulletWorldUnman;
259 return new BulletShapeUnman(
260 BSAPICPP.CreateGImpactShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices),
261 BSPhysicsShapeType.SHAPE_GIMPACT);
262}
263
254public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls) 264public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls)
255{ 265{
256 BulletWorldUnman worldu = world as BulletWorldUnman; 266 BulletWorldUnman worldu = world as BulletWorldUnman;
257 return new BulletShapeUnman( 267 return new BulletShapeUnman(
258 BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls), 268 BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls),
259 BSPhysicsShapeType.SHAPE_HULL); 269 BSPhysicsShapeType.SHAPE_HULL);
260} 270}
261 271
@@ -268,6 +278,25 @@ public override BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShap
268 BSPhysicsShapeType.SHAPE_HULL); 278 BSPhysicsShapeType.SHAPE_HULL);
269} 279}
270 280
281public override BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
282{
283 BulletWorldUnman worldu = world as BulletWorldUnman;
284 BulletShapeUnman shapeu = meshShape as BulletShapeUnman;
285 return new BulletShapeUnman(
286 BSAPICPP.BuildConvexHullShapeFromMesh2(worldu.ptr, shapeu.ptr),
287 BSPhysicsShapeType.SHAPE_CONVEXHULL);
288}
289
290public override BulletShape CreateConvexHullShape(BulletWorld world,
291 int indicesCount, int[] indices,
292 int verticesCount, float[] vertices)
293{
294 BulletWorldUnman worldu = world as BulletWorldUnman;
295 return new BulletShapeUnman(
296 BSAPICPP.CreateConvexHullShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices),
297 BSPhysicsShapeType.SHAPE_CONVEXHULL);
298}
299
271public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData) 300public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData)
272{ 301{
273 BulletWorldUnman worldu = world as BulletWorldUnman; 302 BulletWorldUnman worldu = world as BulletWorldUnman;
@@ -356,7 +385,7 @@ public override BulletShape DuplicateCollisionShape(BulletWorld world, BulletSha
356{ 385{
357 BulletWorldUnman worldu = world as BulletWorldUnman; 386 BulletWorldUnman worldu = world as BulletWorldUnman;
358 BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman; 387 BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman;
359 return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.type); 388 return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.shapeType);
360} 389}
361 390
362public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape) 391public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape)
@@ -567,6 +596,60 @@ public override bool SetBreakingImpulseThreshold(BulletConstraint constrain, flo
567 return BSAPICPP.SetBreakingImpulseThreshold2(constrainu.ptr, threshold); 596 return BSAPICPP.SetBreakingImpulseThreshold2(constrainu.ptr, threshold);
568} 597}
569 598
599public override bool HingeSetLimits(BulletConstraint constrain, float low, float high, float softness, float bias, float relaxation)
600{
601 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
602 return BSAPICPP.HingeSetLimits2(constrainu.ptr, low, high, softness, bias, relaxation);
603}
604
605public override bool SpringEnable(BulletConstraint constrain, int index, float numericTrueFalse)
606{
607 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
608 return BSAPICPP.ConstraintSpringEnable2(constrainu.ptr, index, numericTrueFalse);
609}
610
611public override bool SpringSetEquilibriumPoint(BulletConstraint constrain, int index, float equilibriumPoint)
612{
613 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
614 return BSAPICPP.ConstraintSpringSetEquilibriumPoint2(constrainu.ptr, index, equilibriumPoint);
615}
616
617public override bool SpringSetStiffness(BulletConstraint constrain, int index, float stiffnesss)
618{
619 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
620 return BSAPICPP.ConstraintSpringSetStiffness2(constrainu.ptr, index, stiffnesss);
621}
622
623public override bool SpringSetDamping(BulletConstraint constrain, int index, float damping)
624{
625 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
626 return BSAPICPP.ConstraintSpringSetDamping2(constrainu.ptr, index, damping);
627}
628
629public override bool SliderSetLimits(BulletConstraint constrain, int lowerUpper, int linAng, float val)
630{
631 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
632 return BSAPICPP.SliderSetLimits2(constrainu.ptr, lowerUpper, linAng, val);
633}
634
635public override bool SliderSet(BulletConstraint constrain, int softRestDamp, int dirLimOrtho, int linAng, float val)
636{
637 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
638 return BSAPICPP.SliderSet2(constrainu.ptr, softRestDamp, dirLimOrtho, linAng, val);
639}
640
641public override bool SliderMotorEnable(BulletConstraint constrain, int linAng, float numericTrueFalse)
642{
643 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
644 return BSAPICPP.SliderMotorEnable2(constrainu.ptr, linAng, numericTrueFalse);
645}
646
647public override bool SliderMotor(BulletConstraint constrain, int forceVel, int linAng, float val)
648{
649 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
650 return BSAPICPP.SliderMotor2(constrainu.ptr, forceVel, linAng, val);
651}
652
570public override bool CalculateTransforms(BulletConstraint constrain) 653public override bool CalculateTransforms(BulletConstraint constrain)
571{ 654{
572 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; 655 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
@@ -642,6 +725,13 @@ public override bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj)
642 return BSAPICPP.RemoveObjectFromWorld2(worldu.ptr, bodyu.ptr); 725 return BSAPICPP.RemoveObjectFromWorld2(worldu.ptr, bodyu.ptr);
643} 726}
644 727
728public override bool ClearCollisionProxyCache(BulletWorld world, BulletBody obj)
729{
730 BulletWorldUnman worldu = world as BulletWorldUnman;
731 BulletBodyUnman bodyu = obj as BulletBodyUnman;
732 return BSAPICPP.ClearCollisionProxyCache2(worldu.ptr, bodyu.ptr);
733}
734
645public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects) 735public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects)
646{ 736{
647 BulletWorldUnman worldu = world as BulletWorldUnman; 737 BulletWorldUnman worldu = world as BulletWorldUnman;
@@ -1407,6 +1497,11 @@ public static extern IntPtr CreateMeshShape2(IntPtr world,
1407 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); 1497 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1408 1498
1409[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1500public static extern IntPtr CreateGImpactShape2(IntPtr world,
1501 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
1502 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1503
1504[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1410public static extern IntPtr CreateHullShape2(IntPtr world, 1505public static extern IntPtr CreateHullShape2(IntPtr world,
1411 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); 1506 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
1412 1507
@@ -1414,6 +1509,14 @@ public static extern IntPtr CreateHullShape2(IntPtr world,
1414public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape, HACDParams parms); 1509public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape, HACDParams parms);
1415 1510
1416[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1511[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1512public static extern IntPtr BuildConvexHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
1513
1514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1515public static extern IntPtr CreateConvexHullShape2(IntPtr world,
1516 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
1517 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1518
1519[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1417public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); 1520public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
1418 1521
1419[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1522[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -1476,7 +1579,7 @@ public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
1476public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); 1579public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
1477 1580
1478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1581[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1479public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight, 1582public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight,
1480 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, 1583 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap,
1481 float scaleFactor, float collisionMargin); 1584 float scaleFactor, float collisionMargin);
1482 1585
@@ -1559,6 +1662,33 @@ public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enabl
1559public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold); 1662public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
1560 1663
1561[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1664[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1665public static extern bool HingeSetLimits2(IntPtr constrain, float low, float high, float softness, float bias, float relaxation);
1666
1667[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1668public static extern bool ConstraintSpringEnable2(IntPtr constrain, int index, float numericTrueFalse);
1669
1670[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1671public static extern bool ConstraintSpringSetEquilibriumPoint2(IntPtr constrain, int index, float equilibriumPoint);
1672
1673[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1674public static extern bool ConstraintSpringSetStiffness2(IntPtr constrain, int index, float stiffness);
1675
1676[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1677public static extern bool ConstraintSpringSetDamping2(IntPtr constrain, int index, float damping);
1678
1679[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1680public static extern bool SliderSetLimits2(IntPtr constrain, int lowerUpper, int linAng, float val);
1681
1682[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1683public static extern bool SliderSet2(IntPtr constrain, int softRestDamp, int dirLimOrtho, int linAng, float val);
1684
1685[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1686public static extern bool SliderMotorEnable2(IntPtr constrain, int linAng, float numericTrueFalse);
1687
1688[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1689public static extern bool SliderMotor2(IntPtr constrain, int forceVel, int linAng, float val);
1690
1691[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1562public static extern bool CalculateTransforms2(IntPtr constrain); 1692public static extern bool CalculateTransforms2(IntPtr constrain);
1563 1693
1564[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1694[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -1590,6 +1720,9 @@ public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
1590public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); 1720public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
1591 1721
1592[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1722[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1723public static extern bool ClearCollisionProxyCache2(IntPtr world, IntPtr obj);
1724
1725[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1593public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects); 1726public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
1594 1727
1595[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1728[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index f6b4359..17ebed2 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -81,11 +81,11 @@ private sealed class BulletBodyXNA : BulletBody
81private sealed class BulletShapeXNA : BulletShape 81private sealed class BulletShapeXNA : BulletShape
82{ 82{
83 public CollisionShape shape; 83 public CollisionShape shape;
84 public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ) 84 public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ)
85 : base() 85 : base()
86 { 86 {
87 shape = xx; 87 shape = xx;
88 type = typ; 88 shapeType = typ;
89 } 89 }
90 public override bool HasPhysicalShape 90 public override bool HasPhysicalShape
91 { 91 {
@@ -97,7 +97,7 @@ private sealed class BulletShapeXNA : BulletShape
97 } 97 }
98 public override BulletShape Clone() 98 public override BulletShape Clone()
99 { 99 {
100 return new BulletShapeXNA(shape, type); 100 return new BulletShapeXNA(shape, shapeType);
101 } 101 }
102 public override bool ReferenceSame(BulletShape other) 102 public override bool ReferenceSame(BulletShape other)
103 { 103 {
@@ -137,8 +137,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
137 internal int LastEntityProperty = 0; 137 internal int LastEntityProperty = 0;
138 138
139 internal EntityProperties[] UpdatedObjects; 139 internal EntityProperties[] UpdatedObjects;
140 internal Dictionary<uint, GhostObject> specialCollisionObjects; 140 internal Dictionary<uint, GhostObject> specialCollisionObjects;
141 141
142 private static int m_collisionsThisFrame; 142 private static int m_collisionsThisFrame;
143 private BSScene PhysicsScene { get; set; } 143 private BSScene PhysicsScene { get; set; }
144 144
@@ -151,7 +151,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
151 } 151 }
152 152
153 /// <summary> 153 /// <summary>
154 /// 154 ///
155 /// </summary> 155 /// </summary>
156 /// <param name="p"></param> 156 /// <param name="p"></param>
157 /// <param name="p_2"></param> 157 /// <param name="p_2"></param>
@@ -169,12 +169,25 @@ private sealed class BulletConstraintXNA : BulletConstraint
169 return true; 169 return true;
170 } 170 }
171 171
172 public override bool ClearCollisionProxyCache(BulletWorld pWorld, BulletBody pBody)
173 {
174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
175 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
176 CollisionObject collisionObject = ((BulletBodyXNA)pBody).body;
177 if (body != null && collisionObject != null && collisionObject.GetBroadphaseHandle() != null)
178 {
179 world.RemoveCollisionObject(collisionObject);
180 world.AddCollisionObject(collisionObject);
181 }
182 return true;
183 }
184
172 public override bool AddConstraintToWorld(BulletWorld pWorld, BulletConstraint pConstraint, bool pDisableCollisionsBetweenLinkedObjects) 185 public override bool AddConstraintToWorld(BulletWorld pWorld, BulletConstraint pConstraint, bool pDisableCollisionsBetweenLinkedObjects)
173 { 186 {
174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 187 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
175 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain; 188 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain;
176 world.AddConstraint(constraint, pDisableCollisionsBetweenLinkedObjects); 189 world.AddConstraint(constraint, pDisableCollisionsBetweenLinkedObjects);
177 190
178 return true; 191 return true;
179 192
180 } 193 }
@@ -300,7 +313,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
300 public override bool GetForceUpdateAllAabbs(BulletWorld pWorld) { 313 public override bool GetForceUpdateAllAabbs(BulletWorld pWorld) {
301 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 314 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
302 return world.GetForceUpdateAllAabbs(); 315 return world.GetForceUpdateAllAabbs();
303 316
304 } 317 }
305 public override void SetForceUpdateAllAabbs(BulletWorld pWorld, bool pForce) 318 public override void SetForceUpdateAllAabbs(BulletWorld pWorld, bool pForce)
306 { 319 {
@@ -404,7 +417,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
404 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion); 417 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion);
405 mat._origin = vposition; 418 mat._origin = vposition;
406 collisionObject.SetWorldTransform(mat); 419 collisionObject.SetWorldTransform(mat);
407 420
408 } 421 }
409 422
410 public override Vector3 GetPosition(BulletBody pCollisionObject) 423 public override Vector3 GetPosition(BulletBody pCollisionObject)
@@ -457,7 +470,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
457 { 470 {
458 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 471 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
459 collisionObject.Activate(pforceactivation); 472 collisionObject.Activate(pforceactivation);
460 473
461 } 474 }
462 475
463 public override Quaternion GetOrientation(BulletBody pCollisionObject) 476 public override Quaternion GetOrientation(BulletBody pCollisionObject)
@@ -486,7 +499,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
486 { 499 {
487 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 500 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
488 return collisionObject.GetCcdSweptSphereRadius(); 501 return collisionObject.GetCcdSweptSphereRadius();
489 502
490 } 503 }
491 504
492 public override IntPtr GetUserPointer(BulletBody pCollisionObject) 505 public override IntPtr GetUserPointer(BulletBody pCollisionObject)
@@ -559,8 +572,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
559 } 572 }
560 573
561 574
562 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, 575 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
563 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, 576 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
564 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) 577 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
565 578
566 { 579 {
@@ -604,7 +617,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
604 } 617 }
605 618
606 /// <summary> 619 /// <summary>
607 /// 620 ///
608 /// </summary> 621 /// </summary>
609 /// <param name="pWorld"></param> 622 /// <param name="pWorld"></param>
610 /// <param name="pBody1"></param> 623 /// <param name="pBody1"></param>
@@ -752,6 +765,214 @@ private sealed class BulletConstraintXNA : BulletConstraint
752 constraint.SetBreakingImpulseThreshold(threshold); 765 constraint.SetBreakingImpulseThreshold(threshold);
753 return true; 766 return true;
754 } 767 }
768 public override bool HingeSetLimits(BulletConstraint pConstraint, float low, float high, float softness, float bias, float relaxation)
769 {
770 HingeConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as HingeConstraint;
771 if (softness == HINGE_NOT_SPECIFIED)
772 constraint.SetLimit(low, high);
773 else
774 constraint.SetLimit(low, high, softness, bias, relaxation);
775 return true;
776 }
777 public override bool SpringEnable(BulletConstraint pConstraint, int index, float numericTrueFalse)
778 {
779 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
780 constraint.EnableSpring(index, (numericTrueFalse == 0f ? false : true));
781 return true;
782 }
783
784 public override bool SpringSetEquilibriumPoint(BulletConstraint pConstraint, int index, float equilibriumPoint)
785 {
786 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
787 if (index == SPRING_NOT_SPECIFIED)
788 {
789 constraint.SetEquilibriumPoint();
790 }
791 else
792 {
793 if (equilibriumPoint == SPRING_NOT_SPECIFIED)
794 constraint.SetEquilibriumPoint(index);
795 else
796 constraint.SetEquilibriumPoint(index, equilibriumPoint);
797 }
798 return true;
799 }
800
801 public override bool SpringSetStiffness(BulletConstraint pConstraint, int index, float stiffness)
802 {
803 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
804 constraint.SetStiffness(index, stiffness);
805 return true;
806 }
807
808 public override bool SpringSetDamping(BulletConstraint pConstraint, int index, float damping)
809 {
810 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
811 constraint.SetDamping(index, damping);
812 return true;
813 }
814
815 public override bool SliderSetLimits(BulletConstraint pConstraint, int lowerUpper, int linAng, float val)
816 {
817 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
818 switch (lowerUpper)
819 {
820 case SLIDER_LOWER_LIMIT:
821 switch (linAng)
822 {
823 case SLIDER_LINEAR:
824 constraint.SetLowerLinLimit(val);
825 break;
826 case SLIDER_ANGULAR:
827 constraint.SetLowerAngLimit(val);
828 break;
829 }
830 break;
831 case SLIDER_UPPER_LIMIT:
832 switch (linAng)
833 {
834 case SLIDER_LINEAR:
835 constraint.SetUpperLinLimit(val);
836 break;
837 case SLIDER_ANGULAR:
838 constraint.SetUpperAngLimit(val);
839 break;
840 }
841 break;
842 }
843 return true;
844 }
845 public override bool SliderSet(BulletConstraint pConstraint, int softRestDamp, int dirLimOrtho, int linAng, float val)
846 {
847 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
848 switch (softRestDamp)
849 {
850 case SLIDER_SET_SOFTNESS:
851 switch (dirLimOrtho)
852 {
853 case SLIDER_SET_DIRECTION:
854 switch (linAng)
855 {
856 case SLIDER_LINEAR: constraint.SetSoftnessDirLin(val); break;
857 case SLIDER_ANGULAR: constraint.SetSoftnessDirAng(val); break;
858 }
859 break;
860 case SLIDER_SET_LIMIT:
861 switch (linAng)
862 {
863 case SLIDER_LINEAR: constraint.SetSoftnessLimLin(val); break;
864 case SLIDER_ANGULAR: constraint.SetSoftnessLimAng(val); break;
865 }
866 break;
867 case SLIDER_SET_ORTHO:
868 switch (linAng)
869 {
870 case SLIDER_LINEAR: constraint.SetSoftnessOrthoLin(val); break;
871 case SLIDER_ANGULAR: constraint.SetSoftnessOrthoAng(val); break;
872 }
873 break;
874 }
875 break;
876 case SLIDER_SET_RESTITUTION:
877 switch (dirLimOrtho)
878 {
879 case SLIDER_SET_DIRECTION:
880 switch (linAng)
881 {
882 case SLIDER_LINEAR: constraint.SetRestitutionDirLin(val); break;
883 case SLIDER_ANGULAR: constraint.SetRestitutionDirAng(val); break;
884 }
885 break;
886 case SLIDER_SET_LIMIT:
887 switch (linAng)
888 {
889 case SLIDER_LINEAR: constraint.SetRestitutionLimLin(val); break;
890 case SLIDER_ANGULAR: constraint.SetRestitutionLimAng(val); break;
891 }
892 break;
893 case SLIDER_SET_ORTHO:
894 switch (linAng)
895 {
896 case SLIDER_LINEAR: constraint.SetRestitutionOrthoLin(val); break;
897 case SLIDER_ANGULAR: constraint.SetRestitutionOrthoAng(val); break;
898 }
899 break;
900 }
901 break;
902 case SLIDER_SET_DAMPING:
903 switch (dirLimOrtho)
904 {
905 case SLIDER_SET_DIRECTION:
906 switch (linAng)
907 {
908 case SLIDER_LINEAR: constraint.SetDampingDirLin(val); break;
909 case SLIDER_ANGULAR: constraint.SetDampingDirAng(val); break;
910 }
911 break;
912 case SLIDER_SET_LIMIT:
913 switch (linAng)
914 {
915 case SLIDER_LINEAR: constraint.SetDampingLimLin(val); break;
916 case SLIDER_ANGULAR: constraint.SetDampingLimAng(val); break;
917 }
918 break;
919 case SLIDER_SET_ORTHO:
920 switch (linAng)
921 {
922 case SLIDER_LINEAR: constraint.SetDampingOrthoLin(val); break;
923 case SLIDER_ANGULAR: constraint.SetDampingOrthoAng(val); break;
924 }
925 break;
926 }
927 break;
928 }
929 return true;
930 }
931 public override bool SliderMotorEnable(BulletConstraint pConstraint, int linAng, float numericTrueFalse)
932 {
933 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
934 switch (linAng)
935 {
936 case SLIDER_LINEAR:
937 constraint.SetPoweredLinMotor(numericTrueFalse == 0.0 ? false : true);
938 break;
939 case SLIDER_ANGULAR:
940 constraint.SetPoweredAngMotor(numericTrueFalse == 0.0 ? false : true);
941 break;
942 }
943 return true;
944 }
945 public override bool SliderMotor(BulletConstraint pConstraint, int forceVel, int linAng, float val)
946 {
947 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
948 switch (forceVel)
949 {
950 case SLIDER_MOTOR_VELOCITY:
951 switch (linAng)
952 {
953 case SLIDER_LINEAR:
954 constraint.SetTargetLinMotorVelocity(val);
955 break;
956 case SLIDER_ANGULAR:
957 constraint.SetTargetAngMotorVelocity(val);
958 break;
959 }
960 break;
961 case SLIDER_MAX_MOTOR_FORCE:
962 switch (linAng)
963 {
964 case SLIDER_LINEAR:
965 constraint.SetMaxLinMotorForce(val);
966 break;
967 case SLIDER_ANGULAR:
968 constraint.SetMaxAngMotorForce(val);
969 break;
970 }
971 break;
972 }
973 return true;
974 }
975
755 //BulletSimAPI.SetAngularDamping(Prim.PhysBody.ptr, angularDamping); 976 //BulletSimAPI.SetAngularDamping(Prim.PhysBody.ptr, angularDamping);
756 public override void SetAngularDamping(BulletBody pBody, float angularDamping) 977 public override void SetAngularDamping(BulletBody pBody, float angularDamping)
757 { 978 {
@@ -824,7 +1045,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
824 { 1045 {
825 RigidBody body = (pBody as BulletBodyXNA).rigidBody; 1046 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
826 float angularDamping = body.GetAngularDamping(); 1047 float angularDamping = body.GetAngularDamping();
827 body.SetDamping(lin_damping, angularDamping); 1048 body.SetDamping(lin_damping, angularDamping);
828 } 1049 }
829 1050
830 public override float GetLinearDamping(BulletBody pBody) 1051 public override float GetLinearDamping(BulletBody pBody)
@@ -907,7 +1128,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
907 RigidBody bo = co as RigidBody; 1128 RigidBody bo = co as RigidBody;
908 if (bo == null) 1129 if (bo == null)
909 { 1130 {
910 1131
911 if (world.IsInWorld(co)) 1132 if (world.IsInWorld(co))
912 { 1133 {
913 world.RemoveCollisionObject(co); 1134 world.RemoveCollisionObject(co);
@@ -915,7 +1136,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
915 } 1136 }
916 else 1137 else
917 { 1138 {
918 1139
919 if (world.IsInWorld(bo)) 1140 if (world.IsInWorld(bo))
920 { 1141 {
921 world.RemoveRigidBody(bo); 1142 world.RemoveRigidBody(bo);
@@ -947,7 +1168,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
947 1168
948 // TODO: Turn this from a reference copy to a Value Copy. 1169 // TODO: Turn this from a reference copy to a Value Copy.
949 BulletShapeXNA shape2 = new BulletShapeXNA(shape1, BSShapeTypeFromBroadPhaseNativeType(shape1.GetShapeType())); 1170 BulletShapeXNA shape2 = new BulletShapeXNA(shape1, BSShapeTypeFromBroadPhaseNativeType(shape1.GetShapeType()));
950 1171
951 return shape2; 1172 return shape2;
952 } 1173 }
953 1174
@@ -957,7 +1178,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
957 return false; 1178 return false;
958 } 1179 }
959 //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation); 1180 //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation);
960 1181
961 public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) 1182 public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
962 { 1183 {
963 CollisionWorld world = (pWorld as BulletWorldXNA).world; 1184 CollisionWorld world = (pWorld as BulletWorldXNA).world;
@@ -993,11 +1214,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
993 m_startWorldTransform = IndexedMatrix.Identity; 1214 m_startWorldTransform = IndexedMatrix.Identity;
994 */ 1215 */
995 body.SetUserPointer(pLocalID); 1216 body.SetUserPointer(pLocalID);
996 1217
997 return new BulletBodyXNA(pLocalID, body); 1218 return new BulletBodyXNA(pLocalID, body);
998 } 1219 }
999 1220
1000 1221
1001 public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) 1222 public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
1002 { 1223 {
1003 1224
@@ -1025,7 +1246,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1025 public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain) 1246 public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain)
1026 { 1247 {
1027 1248
1028 /* TODO */ 1249 /* TODO */
1029 return Vector3.Zero; 1250 return Vector3.Zero;
1030 } 1251 }
1031 public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; } 1252 public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; }
@@ -1035,7 +1256,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1035 { 1256 {
1036 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 1257 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1037 return collisionObject.IsStaticObject(); 1258 return collisionObject.IsStaticObject();
1038 1259
1039 } 1260 }
1040 public override bool IsKinematicObject(BulletBody pCollisionObject) 1261 public override bool IsKinematicObject(BulletBody pCollisionObject)
1041 { 1262 {
@@ -1098,10 +1319,10 @@ private sealed class BulletConstraintXNA : BulletConstraint
1098 return new BulletWorldXNA(1, PhysicsScene, BSAPIXNA.Initialize2(worldExtent, configparms, maxCollisions, ref collisionArray, maxUpdates, ref updateArray, null)); 1319 return new BulletWorldXNA(1, PhysicsScene, BSAPIXNA.Initialize2(worldExtent, configparms, maxCollisions, ref collisionArray, maxUpdates, ref updateArray, null));
1099 } 1320 }
1100 1321
1101 private static DiscreteDynamicsWorld Initialize2(Vector3 worldExtent, 1322 private static DiscreteDynamicsWorld Initialize2(Vector3 worldExtent,
1102 ConfigurationParameters[] o, 1323 ConfigurationParameters[] o,
1103 int mMaxCollisionsPerFrame, ref CollisionDesc[] collisionArray, 1324 int mMaxCollisionsPerFrame, ref CollisionDesc[] collisionArray,
1104 int mMaxUpdatesPerFrame, ref EntityProperties[] updateArray, 1325 int mMaxUpdatesPerFrame, ref EntityProperties[] updateArray,
1105 object mDebugLogCallbackHandle) 1326 object mDebugLogCallbackHandle)
1106 { 1327 {
1107 CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData(); 1328 CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData();
@@ -1138,9 +1359,9 @@ private sealed class BulletConstraintXNA : BulletConstraint
1138 p.avatarCapsuleDepth = BSParam.AvatarCapsuleDepth; 1359 p.avatarCapsuleDepth = BSParam.AvatarCapsuleDepth;
1139 p.avatarCapsuleHeight = BSParam.AvatarCapsuleHeight; 1360 p.avatarCapsuleHeight = BSParam.AvatarCapsuleHeight;
1140 p.avatarContactProcessingThreshold = BSParam.AvatarContactProcessingThreshold; 1361 p.avatarContactProcessingThreshold = BSParam.AvatarContactProcessingThreshold;
1141 1362
1142 p.vehicleAngularDamping = BSParam.VehicleAngularDamping; 1363 p.vehicleAngularDamping = BSParam.VehicleAngularDamping;
1143 1364
1144 p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize; 1365 p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize;
1145 p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize; 1366 p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize;
1146 p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation; 1367 p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation;
@@ -1160,7 +1381,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1160 p.linkConstraintSolverIterations = BSParam.LinkConstraintSolverIterations; 1381 p.linkConstraintSolverIterations = BSParam.LinkConstraintSolverIterations;
1161 p.physicsLoggingFrames = o[0].physicsLoggingFrames; 1382 p.physicsLoggingFrames = o[0].physicsLoggingFrames;
1162 DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo(); 1383 DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo();
1163 1384
1164 DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration(); 1385 DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration();
1165 CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci); 1386 CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci);
1166 1387
@@ -1221,6 +1442,50 @@ private sealed class BulletConstraintXNA : BulletConstraint
1221 //BSParam.TerrainImplementation = 0; 1442 //BSParam.TerrainImplementation = 0;
1222 world.SetGravity(new IndexedVector3(0,0,p.gravity)); 1443 world.SetGravity(new IndexedVector3(0,0,p.gravity));
1223 1444
1445 // Turn off Pooling since globals and pooling are bad for threading.
1446 BulletGlobals.VoronoiSimplexSolverPool.SetPoolingEnabled(false);
1447 BulletGlobals.SubSimplexConvexCastPool.SetPoolingEnabled(false);
1448 BulletGlobals.ManifoldPointPool.SetPoolingEnabled(false);
1449 BulletGlobals.CastResultPool.SetPoolingEnabled(false);
1450 BulletGlobals.SphereShapePool.SetPoolingEnabled(false);
1451 BulletGlobals.DbvtNodePool.SetPoolingEnabled(false);
1452 BulletGlobals.SingleRayCallbackPool.SetPoolingEnabled(false);
1453 BulletGlobals.SubSimplexClosestResultPool.SetPoolingEnabled(false);
1454 BulletGlobals.GjkPairDetectorPool.SetPoolingEnabled(false);
1455 BulletGlobals.DbvtTreeColliderPool.SetPoolingEnabled(false);
1456 BulletGlobals.SingleSweepCallbackPool.SetPoolingEnabled(false);
1457 BulletGlobals.BroadphaseRayTesterPool.SetPoolingEnabled(false);
1458 BulletGlobals.ClosestNotMeConvexResultCallbackPool.SetPoolingEnabled(false);
1459 BulletGlobals.GjkEpaPenetrationDepthSolverPool.SetPoolingEnabled(false);
1460 BulletGlobals.ContinuousConvexCollisionPool.SetPoolingEnabled(false);
1461 BulletGlobals.DbvtStackDataBlockPool.SetPoolingEnabled(false);
1462
1463 BulletGlobals.BoxBoxCollisionAlgorithmPool.SetPoolingEnabled(false);
1464 BulletGlobals.CompoundCollisionAlgorithmPool.SetPoolingEnabled(false);
1465 BulletGlobals.ConvexConcaveCollisionAlgorithmPool.SetPoolingEnabled(false);
1466 BulletGlobals.ConvexConvexAlgorithmPool.SetPoolingEnabled(false);
1467 BulletGlobals.ConvexPlaneAlgorithmPool.SetPoolingEnabled(false);
1468 BulletGlobals.SphereBoxCollisionAlgorithmPool.SetPoolingEnabled(false);
1469 BulletGlobals.SphereSphereCollisionAlgorithmPool.SetPoolingEnabled(false);
1470 BulletGlobals.SphereTriangleCollisionAlgorithmPool.SetPoolingEnabled(false);
1471 BulletGlobals.GImpactCollisionAlgorithmPool.SetPoolingEnabled(false);
1472 BulletGlobals.GjkEpaSolver2MinkowskiDiffPool.SetPoolingEnabled(false);
1473 BulletGlobals.PersistentManifoldPool.SetPoolingEnabled(false);
1474 BulletGlobals.ManifoldResultPool.SetPoolingEnabled(false);
1475 BulletGlobals.GJKPool.SetPoolingEnabled(false);
1476 BulletGlobals.GIM_ShapeRetrieverPool.SetPoolingEnabled(false);
1477 BulletGlobals.TriangleShapePool.SetPoolingEnabled(false);
1478 BulletGlobals.SphereTriangleDetectorPool.SetPoolingEnabled(false);
1479 BulletGlobals.CompoundLeafCallbackPool.SetPoolingEnabled(false);
1480 BulletGlobals.GjkConvexCastPool.SetPoolingEnabled(false);
1481 BulletGlobals.LocalTriangleSphereCastCallbackPool.SetPoolingEnabled(false);
1482 BulletGlobals.BridgeTriangleRaycastCallbackPool.SetPoolingEnabled(false);
1483 BulletGlobals.BridgeTriangleConcaveRaycastCallbackPool.SetPoolingEnabled(false);
1484 BulletGlobals.BridgeTriangleConvexcastCallbackPool.SetPoolingEnabled(false);
1485 BulletGlobals.MyNodeOverlapCallbackPool.SetPoolingEnabled(false);
1486 BulletGlobals.ClosestRayResultCallbackPool.SetPoolingEnabled(false);
1487 BulletGlobals.DebugDrawcallbackPool.SetPoolingEnabled(false);
1488
1224 return world; 1489 return world;
1225 } 1490 }
1226 //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL 1491 //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL
@@ -1263,7 +1528,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1263 } 1528 }
1264 } 1529 }
1265 return ret; 1530 return ret;
1266 1531
1267 } 1532 }
1268 1533
1269 public override float GetAngularMotionDisc(BulletShape pShape) 1534 public override float GetAngularMotionDisc(BulletShape pShape)
@@ -1353,10 +1618,10 @@ private sealed class BulletConstraintXNA : BulletConstraint
1353 CollisionShape shape = (pShape as BulletShapeXNA).shape; 1618 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1354 gObj.SetCollisionShape(shape); 1619 gObj.SetCollisionShape(shape);
1355 gObj.SetUserPointer(pLocalID); 1620 gObj.SetUserPointer(pLocalID);
1356 1621
1357 if (specialCollisionObjects.ContainsKey(pLocalID)) 1622 if (specialCollisionObjects.ContainsKey(pLocalID))
1358 specialCollisionObjects[pLocalID] = gObj; 1623 specialCollisionObjects[pLocalID] = gObj;
1359 else 1624 else
1360 specialCollisionObjects.Add(pLocalID, gObj); 1625 specialCollisionObjects.Add(pLocalID, gObj);
1361 1626
1362 // TODO: Add to Special CollisionObjects! 1627 // TODO: Add to Special CollisionObjects!
@@ -1447,8 +1712,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
1447 return new BulletShapeXNA(ret, BSShapeTypeFromBroadPhaseNativeType(ret.GetShapeType())); 1712 return new BulletShapeXNA(ret, BSShapeTypeFromBroadPhaseNativeType(ret.GetShapeType()));
1448 } 1713 }
1449 1714
1450 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { 1715 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) {
1451 1716
1452 if (cShape == null) 1717 if (cShape == null)
1453 return null; 1718 return null;
1454 CompoundShape compoundShape = (cShape as BulletShapeXNA).shape as CompoundShape; 1719 CompoundShape compoundShape = (cShape as BulletShapeXNA).shape as CompoundShape;
@@ -1456,7 +1721,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1456 BulletShape retShape = new BulletShapeXNA(shape, BSShapeTypeFromBroadPhaseNativeType(shape.GetShapeType())); 1721 BulletShape retShape = new BulletShapeXNA(shape, BSShapeTypeFromBroadPhaseNativeType(shape.GetShapeType()));
1457 1722
1458 1723
1459 return retShape; 1724 return retShape;
1460 } 1725 }
1461 1726
1462 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin) 1727 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin)
@@ -1475,7 +1740,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1475 ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 1740 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1476 break; 1741 break;
1477 case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE: 1742 case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE:
1478 ret = BSPhysicsShapeType.SHAPE_MESH; 1743 ret = BSPhysicsShapeType.SHAPE_CONVEXHULL;
1479 break; 1744 break;
1480 case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE: 1745 case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE:
1481 ret = BSPhysicsShapeType.SHAPE_HULL; 1746 ret = BSPhysicsShapeType.SHAPE_HULL;
@@ -1503,7 +1768,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1503 ret = BSPhysicsShapeType.SHAPE_CONE; 1768 ret = BSPhysicsShapeType.SHAPE_CONE;
1504 break; 1769 break;
1505 case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE: 1770 case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE:
1506 ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 1771 ret = BSPhysicsShapeType.SHAPE_CONVEXHULL;
1507 break; 1772 break;
1508 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE: 1773 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
1509 ret = BSPhysicsShapeType.SHAPE_CYLINDER; 1774 ret = BSPhysicsShapeType.SHAPE_CYLINDER;
@@ -1547,7 +1812,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1547 break; 1812 break;
1548 ///Used for GIMPACT Trimesh integration 1813 ///Used for GIMPACT Trimesh integration
1549 case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE: 1814 case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE:
1550 ret = BSPhysicsShapeType.SHAPE_MESH; 1815 ret = BSPhysicsShapeType.SHAPE_GIMPACT;
1551 break; 1816 break;
1552 ///Multimaterial mesh 1817 ///Multimaterial mesh
1553 case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE: 1818 case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE:
@@ -1598,8 +1863,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
1598 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE); 1863 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE);
1599 } 1864 }
1600 1865
1601 public override BulletConstraint Create6DofSpringConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, 1866 public override BulletConstraint Create6DofSpringConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
1602 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, 1867 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
1603 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) 1868 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
1604 1869
1605 { 1870 {
@@ -1745,7 +2010,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1745 { 2010 {
1746 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 2011 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1747 CompoundShape compoundshape = new CompoundShape(false); 2012 CompoundShape compoundshape = new CompoundShape(false);
1748 2013
1749 compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin); 2014 compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin);
1750 int ii = 1; 2015 int ii = 1;
1751 2016
@@ -1761,7 +2026,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1761 int ender = ((ii + 4) + (vertexCount*3)); 2026 int ender = ((ii + 4) + (vertexCount*3));
1762 for (int iii = ii + 4; iii < ender; iii+=3) 2027 for (int iii = ii + 4; iii < ender; iii+=3)
1763 { 2028 {
1764 2029
1765 virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2])); 2030 virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2]));
1766 } 2031 }
1767 ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount); 2032 ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount);
@@ -1769,7 +2034,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1769 compoundshape.AddChildShape(ref childTrans, convexShape); 2034 compoundshape.AddChildShape(ref childTrans, convexShape);
1770 ii += (vertexCount*3 + 4); 2035 ii += (vertexCount*3 + 4);
1771 } 2036 }
1772 2037
1773 return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL); 2038 return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL);
1774 } 2039 }
1775 2040
@@ -1778,16 +2043,26 @@ private sealed class BulletConstraintXNA : BulletConstraint
1778 /* TODO */ return null; 2043 /* TODO */ return null;
1779 } 2044 }
1780 2045
2046 public override BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
2047 {
2048 /* TODO */ return null;
2049 }
2050
2051 public override BulletShape CreateConvexHullShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
2052 {
2053 /* TODO */ return null;
2054 }
2055
1781 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats) 2056 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
1782 { 2057 {
1783 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount); 2058 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount);
1784 2059
1785 for (int iter = 0; iter < pVerticesCount; iter++) 2060 for (int iter = 0; iter < pVerticesCount; iter++)
1786 { 2061 {
1787 if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0; 2062 if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0;
1788 if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0; 2063 if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0;
1789 } 2064 }
1790 2065
1791 ObjectArray<int> indicesarr = new ObjectArray<int>(indices); 2066 ObjectArray<int> indicesarr = new ObjectArray<int>(indices);
1792 ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats); 2067 ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats);
1793 DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount); 2068 DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount);
@@ -1801,7 +2076,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1801 mesh.m_vertexStride = 3; 2076 mesh.m_vertexStride = 3;
1802 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; 2077 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1803 mesh.m_triangleIndexStride = 3; 2078 mesh.m_triangleIndexStride = 3;
1804 2079
1805 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); 2080 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1806 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); 2081 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1807 BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true); 2082 BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true);
@@ -1810,9 +2085,14 @@ private sealed class BulletConstraintXNA : BulletConstraint
1810 return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH); 2085 return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH);
1811 2086
1812 } 2087 }
2088 public override BulletShape CreateGImpactShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
2089 {
2090 // TODO:
2091 return null;
2092 }
1813 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount ) 2093 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount )
1814 { 2094 {
1815 2095
1816 String fileName = "objTest3.raw"; 2096 String fileName = "objTest3.raw";
1817 String completePath = System.IO.Path.Combine(Util.configDir(), fileName); 2097 String completePath = System.IO.Path.Combine(Util.configDir(), fileName);
1818 StreamWriter sw = new StreamWriter(completePath); 2098 StreamWriter sw = new StreamWriter(completePath);
@@ -1838,7 +2118,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1838 string s = vertices[indices[i * 3]].ToString("0.0000"); 2118 string s = vertices[indices[i * 3]].ToString("0.0000");
1839 s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000"); 2119 s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000");
1840 s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000"); 2120 s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000");
1841 2121
1842 sw.Write(s + "\n"); 2122 sw.Write(s + "\n");
1843 } 2123 }
1844 2124
@@ -1860,7 +2140,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1860 mesh.m_vertexStride = 3; 2140 mesh.m_vertexStride = 3;
1861 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; 2141 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1862 mesh.m_triangleIndexStride = 3; 2142 mesh.m_triangleIndexStride = 3;
1863 2143
1864 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); 2144 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1865 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); 2145 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1866 2146
@@ -1891,7 +2171,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1891 sw.Close(); 2171 sw.Close();
1892 } 2172 }
1893 2173
1894 public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, 2174 public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
1895 float scaleFactor, float collisionMargin) 2175 float scaleFactor, float collisionMargin)
1896 { 2176 {
1897 const int upAxis = 2; 2177 const int upAxis = 2;
@@ -1899,7 +2179,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1899 heightMap, scaleFactor, 2179 heightMap, scaleFactor,
1900 minHeight, maxHeight, upAxis, 2180 minHeight, maxHeight, upAxis,
1901 false); 2181 false);
1902 terrainShape.SetMargin(collisionMargin + 0.5f); 2182 terrainShape.SetMargin(collisionMargin);
1903 terrainShape.SetUseDiamondSubdivision(true); 2183 terrainShape.SetUseDiamondSubdivision(true);
1904 terrainShape.SetUserPointer(id); 2184 terrainShape.SetUserPointer(id);
1905 return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN); 2185 return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN);
@@ -1933,14 +2213,14 @@ private sealed class BulletConstraintXNA : BulletConstraint
1933 /* TODO */ 2213 /* TODO */
1934 updatedEntityCount = 0; 2214 updatedEntityCount = 0;
1935 collidersCount = 0; 2215 collidersCount = 0;
1936 2216
1937 2217
1938 int ret = PhysicsStep2(world,timeStep,maxSubSteps,fixedTimeStep,out updatedEntityCount,out world.physicsScene.m_updateArray, out collidersCount, out world.physicsScene.m_collisionArray); 2218 int ret = PhysicsStep2(world,timeStep,maxSubSteps,fixedTimeStep,out updatedEntityCount,out world.physicsScene.m_updateArray, out collidersCount, out world.physicsScene.m_collisionArray);
1939 2219
1940 return ret; 2220 return ret;
1941 } 2221 }
1942 2222
1943 private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep, 2223 private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep,
1944 out int updatedEntityCount, out EntityProperties[] updatedEntities, 2224 out int updatedEntityCount, out EntityProperties[] updatedEntities,
1945 out int collidersCount, out CollisionDesc[] colliders) 2225 out int collidersCount, out CollisionDesc[] colliders)
1946 { 2226 {
@@ -1949,24 +2229,24 @@ private sealed class BulletConstraintXNA : BulletConstraint
1949 return epic; 2229 return epic;
1950 } 2230 }
1951 2231
1952 private int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount, 2232 private int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount,
1953 out EntityProperties[] updatedEntities, out int collidersCount, out CollisionDesc[] colliders, int maxCollisions, int maxUpdates) 2233 out EntityProperties[] updatedEntities, out int collidersCount, out CollisionDesc[] colliders, int maxCollisions, int maxUpdates)
1954 { 2234 {
1955 int numSimSteps = 0; 2235 int numSimSteps = 0;
1956 Array.Clear(UpdatedObjects, 0, UpdatedObjects.Length); 2236 Array.Clear(UpdatedObjects, 0, UpdatedObjects.Length);
1957 Array.Clear(UpdatedCollisions, 0, UpdatedCollisions.Length); 2237 Array.Clear(UpdatedCollisions, 0, UpdatedCollisions.Length);
1958 LastEntityProperty=0; 2238 LastEntityProperty=0;
1959 2239
1960 2240
1961 2241
1962 2242
1963 2243
1964 2244
1965 LastCollisionDesc=0; 2245 LastCollisionDesc=0;
1966 2246
1967 updatedEntityCount = 0; 2247 updatedEntityCount = 0;
1968 collidersCount = 0; 2248 collidersCount = 0;
1969 2249
1970 2250
1971 if (pWorld is BulletWorldXNA) 2251 if (pWorld is BulletWorldXNA)
1972 { 2252 {
@@ -2023,7 +2303,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2023 2303
2024 collidersCount = LastCollisionDesc; 2304 collidersCount = LastCollisionDesc;
2025 colliders = UpdatedCollisions; 2305 colliders = UpdatedCollisions;
2026 2306
2027 2307
2028 } 2308 }
2029 else 2309 else
@@ -2031,15 +2311,15 @@ private sealed class BulletConstraintXNA : BulletConstraint
2031 //if (updatedEntities is null) 2311 //if (updatedEntities is null)
2032 //updatedEntities = new List<BulletXNA.EntityProperties>(); 2312 //updatedEntities = new List<BulletXNA.EntityProperties>();
2033 //updatedEntityCount = 0; 2313 //updatedEntityCount = 0;
2034 2314
2035 2315
2036 //collidersCount = 0; 2316 //collidersCount = 0;
2037 2317
2038 updatedEntities = new EntityProperties[0]; 2318 updatedEntities = new EntityProperties[0];
2039 2319
2040 2320
2041 colliders = new CollisionDesc[0]; 2321 colliders = new CollisionDesc[0];
2042 2322
2043 } 2323 }
2044 return numSimSteps; 2324 return numSimSteps;
2045 } 2325 }
@@ -2047,7 +2327,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2047 { 2327 {
2048 IOverlappingPairCache cache = obj.GetOverlappingPairCache(); 2328 IOverlappingPairCache cache = obj.GetOverlappingPairCache();
2049 ObjectArray<BroadphasePair> pairs = cache.GetOverlappingPairArray(); 2329 ObjectArray<BroadphasePair> pairs = cache.GetOverlappingPairArray();
2050 2330
2051 DiscreteDynamicsWorld world = (PhysicsScene.World as BulletWorldXNA).world; 2331 DiscreteDynamicsWorld world = (PhysicsScene.World as BulletWorldXNA).world;
2052 PersistentManifoldArray manifoldArray = new PersistentManifoldArray(); 2332 PersistentManifoldArray manifoldArray = new PersistentManifoldArray();
2053 BroadphasePair collisionPair; 2333 BroadphasePair collisionPair;
@@ -2059,7 +2339,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2059 ManifoldPoint pt; 2339 ManifoldPoint pt;
2060 2340
2061 int numPairs = pairs.Count; 2341 int numPairs = pairs.Count;
2062 2342
2063 for (int i = 0; i < numPairs; i++) 2343 for (int i = 0; i < numPairs; i++)
2064 { 2344 {
2065 manifoldArray.Clear(); 2345 manifoldArray.Clear();
@@ -2068,7 +2348,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2068 collisionPair = world.GetPairCache().FindPair(pairs[i].m_pProxy0, pairs[i].m_pProxy1); 2348 collisionPair = world.GetPairCache().FindPair(pairs[i].m_pProxy0, pairs[i].m_pProxy1);
2069 if (collisionPair == null) 2349 if (collisionPair == null)
2070 continue; 2350 continue;
2071 2351
2072 collisionPair.m_algorithm.GetAllContactManifolds(manifoldArray); 2352 collisionPair.m_algorithm.GetAllContactManifolds(manifoldArray);
2073 for (int j = 0; j < manifoldArray.Count; j++) 2353 for (int j = 0; j < manifoldArray.Count; j++)
2074 { 2354 {
@@ -2091,7 +2371,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2091 } 2371 }
2092 private static void RecordCollision(BSAPIXNA world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm, float penetration) 2372 private static void RecordCollision(BSAPIXNA world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm, float penetration)
2093 { 2373 {
2094 2374
2095 IndexedVector3 contactNormal = norm; 2375 IndexedVector3 contactNormal = norm;
2096 if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 && 2376 if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 &&
2097 (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0) 2377 (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0)
@@ -2161,11 +2441,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
2161 if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody) 2441 if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody)
2162 { 2442 {
2163 CollisionObject AvoidBody = (NotMe as BulletBodyXNA).body; 2443 CollisionObject AvoidBody = (NotMe as BulletBodyXNA).body;
2164 2444
2165 IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z); 2445 IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z);
2166 IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight); 2446 IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight);
2167 using ( 2447 using (
2168 ClosestNotMeRayResultCallback rayCallback = 2448 ClosestNotMeRayResultCallback rayCallback =
2169 new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody) 2449 new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody)
2170 ) 2450 )
2171 { 2451 {
@@ -2181,9 +2461,9 @@ private sealed class BulletConstraintXNA : BulletConstraint
2181 return false; 2461 return false;
2182 } 2462 }
2183} 2463}
2184
2185 2464
2186 2465
2466
2187 2467
2188 public class SimMotionState : DefaultMotionState 2468 public class SimMotionState : DefaultMotionState
2189 { 2469 {
@@ -2276,12 +2556,12 @@ private sealed class BulletConstraintXNA : BulletConstraint
2276 m_lastProperties = m_properties; 2556 m_lastProperties = m_properties;
2277 if (m_world.LastEntityProperty < m_world.UpdatedObjects.Length) 2557 if (m_world.LastEntityProperty < m_world.UpdatedObjects.Length)
2278 m_world.UpdatedObjects[m_world.LastEntityProperty++]=(m_properties); 2558 m_world.UpdatedObjects[m_world.LastEntityProperty++]=(m_properties);
2279 2559
2280 //(*m_updatesThisFrame)[m_properties.ID] = &m_properties; 2560 //(*m_updatesThisFrame)[m_properties.ID] = &m_properties;
2281 } 2561 }
2282 2562
2283 2563
2284 2564
2285 2565
2286 } 2566 }
2287 public override void SetRigidBody(RigidBody body) 2567 public override void SetRigidBody(RigidBody body)
@@ -2304,7 +2584,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2304 (((v1.Z - nEpsilon) < v2.Z) && (v2.Z < (v1.Z + nEpsilon))) && 2584 (((v1.Z - nEpsilon) < v2.Z) && (v2.Z < (v1.Z + nEpsilon))) &&
2305 (((v1.W - nEpsilon) < v2.W) && (v2.W < (v1.W + nEpsilon))); 2585 (((v1.W - nEpsilon) < v2.W) && (v2.W < (v1.W + nEpsilon)));
2306 } 2586 }
2307 2587
2308 } 2588 }
2309} 2589}
2310 2590
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
new file mode 100755
index 0000000..1bcf879
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -0,0 +1,411 @@
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 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorAvatarMove : BSActor
40{
41 BSVMotor m_velocityMotor;
42
43 // Set to true if we think we're going up stairs.
44 // This state is remembered because collisions will turn on and off as we go up stairs.
45 int m_walkingUpStairs;
46 // The amount the step up is applying. Used to smooth stair walking.
47 float m_lastStepUp;
48
49 // Jumping happens over several frames. If use applies up force while colliding, start the
50 // jump and allow the jump to continue for this number of frames.
51 int m_jumpFrames = 0;
52 float m_jumpVelocity = 0f;
53
54 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
55 : base(physicsScene, pObj, actorName)
56 {
57 m_velocityMotor = null;
58 m_walkingUpStairs = 0;
59 m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID);
60 }
61
62 // BSActor.isActive
63 public override bool isActive
64 {
65 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
66 }
67
68 // Release any connections and resources used by the actor.
69 // BSActor.Dispose()
70 public override void Dispose()
71 {
72 base.SetEnabled(false);
73 // Now that turned off, remove any state we have in the scene.
74 Refresh();
75 }
76
77 // Called when physical parameters (properties set in Bullet) need to be re-applied.
78 // Called at taint-time.
79 // BSActor.Refresh()
80 public override void Refresh()
81 {
82 m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh", m_controllingPrim.LocalID);
83
84 // If the object is physically active, add the hoverer prestep action
85 if (isActive)
86 {
87 ActivateAvatarMove();
88 }
89 else
90 {
91 DeactivateAvatarMove();
92 }
93 }
94
95 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
96 // Register a prestep action to restore physical requirements before the next simulation step.
97 // Called at taint-time.
98 // BSActor.RemoveDependencies()
99 public override void RemoveDependencies()
100 {
101 // Nothing to do for the hoverer since it is all software at pre-step action time.
102 }
103
104 // Usually called when target velocity changes to set the current velocity and the target
105 // into the movement motor.
106 public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime)
107 {
108 m_physicsScene.TaintedObject(inTaintTime, m_controllingPrim.LocalID, "BSActorAvatarMove.setVelocityAndTarget", delegate()
109 {
110 if (m_velocityMotor != null)
111 {
112 m_velocityMotor.Reset();
113 m_velocityMotor.SetTarget(targ);
114 m_velocityMotor.SetCurrent(vel);
115 m_velocityMotor.Enabled = true;
116 }
117 });
118 }
119
120 // If a hover motor has not been created, create one and start the hovering.
121 private void ActivateAvatarMove()
122 {
123 if (m_velocityMotor == null)
124 {
125 // Infinite decay and timescale values so motor only changes current to target values.
126 m_velocityMotor = new BSVMotor("BSCharacter.Velocity",
127 0.2f, // time scale
128 BSMotor.Infinite, // decay time scale
129 1f // efficiency
130 );
131 m_velocityMotor.ErrorZeroThreshold = BSParam.AvatarStopZeroThreshold;
132 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
133 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
134
135 m_physicsScene.BeforeStep += Mover;
136 m_controllingPrim.OnPreUpdateProperty += Process_OnPreUpdateProperty;
137
138 m_walkingUpStairs = 0;
139 }
140 }
141
142 private void DeactivateAvatarMove()
143 {
144 if (m_velocityMotor != null)
145 {
146 m_controllingPrim.OnPreUpdateProperty -= Process_OnPreUpdateProperty;
147 m_physicsScene.BeforeStep -= Mover;
148 m_velocityMotor = null;
149 }
150 }
151
152 // Called just before the simulation step. Update the vertical position for hoverness.
153 private void Mover(float timeStep)
154 {
155 // Don't do movement while the object is selected.
156 if (!isActive)
157 return;
158
159 // TODO: Decide if the step parameters should be changed depending on the avatar's
160 // state (flying, colliding, ...). There is code in ODE to do this.
161
162 // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
163 // specified for the avatar is the one that should be used. For falling, if the avatar
164 // is not flying and is not colliding then it is presumed to be falling and the Z
165 // component is not fooled with (thus allowing gravity to do its thing).
166 // When the avatar is standing, though, the user has specified a velocity of zero and
167 // the avatar should be standing. But if the avatar is pushed by something in the world
168 // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
169 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
170 // errors can creap in and the avatar will slowly float off in some direction.
171 // So, the problem is that, when an avatar is standing, we cannot tell creaping error
172 // from real pushing.
173 // The code below uses whether the collider is static or moving to decide whether to zero motion.
174
175 m_velocityMotor.Step(timeStep);
176 m_controllingPrim.IsStationary = false;
177
178 // If we're not supposed to be moving, make sure things are zero.
179 if (m_velocityMotor.ErrorIsZero() && m_velocityMotor.TargetValue == OMV.Vector3.Zero)
180 {
181 // The avatar shouldn't be moving
182 m_velocityMotor.Zero();
183
184 if (m_controllingPrim.IsColliding)
185 {
186 // If we are colliding with a stationary object, presume we're standing and don't move around
187 if (!m_controllingPrim.ColliderIsMoving && !m_controllingPrim.ColliderIsVolumeDetect)
188 {
189 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID);
190 m_controllingPrim.IsStationary = true;
191 m_controllingPrim.ZeroMotion(true /* inTaintTime */);
192 }
193
194 // Standing has more friction on the ground
195 if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction)
196 {
197 m_controllingPrim.Friction = BSParam.AvatarStandingFriction;
198 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
199 }
200 }
201 else
202 {
203 if (m_controllingPrim.Flying)
204 {
205 // Flying and not colliding and velocity nearly zero.
206 m_controllingPrim.ZeroMotion(true /* inTaintTime */);
207 }
208 }
209
210 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}",
211 m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding);
212 }
213 else
214 {
215 // Supposed to be moving.
216 OMV.Vector3 stepVelocity = m_velocityMotor.CurrentValue;
217
218 if (m_controllingPrim.Friction != BSParam.AvatarFriction)
219 {
220 // Probably starting to walk. Set friction to moving friction.
221 m_controllingPrim.Friction = BSParam.AvatarFriction;
222 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
223 }
224
225 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
226 {
227 stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
228 }
229
230
231 // Colliding and not flying with an upward force. The avatar must be trying to jump.
232 if (!m_controllingPrim.Flying && m_controllingPrim.IsColliding && stepVelocity.Z > 0)
233 {
234 // We allow the upward force to happen for this many frames.
235 m_jumpFrames = BSParam.AvatarJumpFrames;
236 m_jumpVelocity = stepVelocity.Z;
237 }
238
239 // The case where the avatar is not colliding and is not flying is special.
240 // The avatar is either falling or jumping and the user can be applying force to the avatar
241 // (force in some direction or force up or down).
242 // If the avatar has negative Z velocity and is not colliding, presume we're falling and keep the velocity.
243 // If the user is trying to apply upward force but we're not colliding, assume the avatar
244 // is trying to jump and don't apply the upward force if not touching the ground any more.
245 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
246 {
247 // If upward velocity is being applied, this must be a jump and only allow that to go on so long
248 if (m_jumpFrames > 0)
249 {
250 // Since not touching the ground, only apply upward force for so long.
251 m_jumpFrames--;
252 stepVelocity.Z = m_jumpVelocity;
253 }
254 else
255 {
256 // Since we're not affected by anything, whatever vertical motion the avatar has, continue that.
257 stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
258 }
259 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
260 }
261
262 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
263 OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass;
264
265 // Add special movement force to allow avatars to walk up stepped surfaces.
266 moveForce += WalkUpStairs();
267
268 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}",
269 m_controllingPrim.LocalID, stepVelocity, m_controllingPrim.RawVelocity, m_controllingPrim.Mass, moveForce);
270 m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, moveForce);
271 }
272 }
273
274 // Called just as the property update is received from the physics engine.
275 // Do any mode necessary for avatar movement.
276 private void Process_OnPreUpdateProperty(ref EntityProperties entprop)
277 {
278 // Don't change position if standing on a stationary object.
279 if (m_controllingPrim.IsStationary)
280 {
281 entprop.Position = m_controllingPrim.RawPosition;
282 entprop.Velocity = OMV.Vector3.Zero;
283 m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation);
284 }
285
286 }
287
288 // Decide if the character is colliding with a low object and compute a force to pop the
289 // avatar up so it can walk up and over the low objects.
290 private OMV.Vector3 WalkUpStairs()
291 {
292 OMV.Vector3 ret = OMV.Vector3.Zero;
293
294 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}",
295 m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying,
296 m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z);
297
298 // Check for stairs climbing if colliding, not flying and moving forward
299 if ( m_controllingPrim.IsColliding
300 && !m_controllingPrim.Flying
301 && m_controllingPrim.TargetVelocitySpeed > 0.1f )
302 {
303 // The range near the character's feet where we will consider stairs
304 // float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f;
305 // Note: there is a problem with the computation of the capsule height. Thus RawPosition is off
306 // from the height. Revisit size and this computation when height is scaled properly.
307 float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) - 0.05f;
308 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
309
310 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is.
311 // Find the highest 'good' collision.
312 OMV.Vector3 highestTouchPosition = OMV.Vector3.Zero;
313 foreach (KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList)
314 {
315 // Don't care about collisions with the terrain
316 if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID)
317 {
318 BSPhysObject collisionObject;
319 if (m_physicsScene.PhysObjects.TryGetValue(kvp.Key, out collisionObject))
320 {
321 if (!collisionObject.IsVolumeDetect)
322 {
323 OMV.Vector3 touchPosition = kvp.Value.Position;
324 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
325 m_controllingPrim.LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
326 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
327 {
328 // This contact is within the 'near the feet' range.
329 // The normal should be our contact point to the object so it is pointing away
330 // thus the difference between our facing orientation and the normal should be small.
331 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation;
332 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
333 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
334 if (diff < BSParam.AvatarStepApproachFactor)
335 {
336 if (highestTouchPosition.Z < touchPosition.Z)
337 highestTouchPosition = touchPosition;
338 }
339 }
340 }
341 }
342 }
343 }
344 m_walkingUpStairs = 0;
345 // If there is a good step sensing, move the avatar over the step.
346 if (highestTouchPosition != OMV.Vector3.Zero)
347 {
348 // Remember that we are going up stairs. This is needed because collisions
349 // will stop when we move up so this smoothes out that effect.
350 m_walkingUpStairs = BSParam.AvatarStepSmoothingSteps;
351
352 m_lastStepUp = highestTouchPosition.Z - nearFeetHeightMin;
353 ret = ComputeStairCorrection(m_lastStepUp);
354 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},ret={3}",
355 m_controllingPrim.LocalID, highestTouchPosition, nearFeetHeightMin, ret);
356 }
357 }
358 else
359 {
360 // If we used to be going up stairs but are not now, smooth the case where collision goes away while
361 // we are bouncing up the stairs.
362 if (m_walkingUpStairs > 0)
363 {
364 m_walkingUpStairs--;
365 ret = ComputeStairCorrection(m_lastStepUp);
366 }
367 }
368
369 return ret;
370 }
371
372 private OMV.Vector3 ComputeStairCorrection(float stepUp)
373 {
374 OMV.Vector3 ret = OMV.Vector3.Zero;
375 OMV.Vector3 displacement = OMV.Vector3.Zero;
376
377 if (stepUp > 0f)
378 {
379 // Found the stairs contact point. Push up a little to raise the character.
380 if (BSParam.AvatarStepForceFactor > 0f)
381 {
382 float upForce = stepUp * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor;
383 ret = new OMV.Vector3(0f, 0f, upForce);
384 }
385
386 // Also move the avatar up for the new height
387 if (BSParam.AvatarStepUpCorrectionFactor > 0f)
388 {
389 // Move the avatar up related to the height of the collision
390 displacement = new OMV.Vector3(0f, 0f, stepUp * BSParam.AvatarStepUpCorrectionFactor);
391 m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
392 }
393 else
394 {
395 if (BSParam.AvatarStepUpCorrectionFactor < 0f)
396 {
397 // Move the avatar up about the specified step height
398 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight);
399 m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
400 }
401 }
402 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs.ComputeStairCorrection,disp={1},force={2}",
403 m_controllingPrim.LocalID, displacement, ret);
404
405 }
406 return ret;
407 }
408}
409}
410
411
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
new file mode 100755
index 0000000..8a79809
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
@@ -0,0 +1,173 @@
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 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorHover : BSActor
40{
41 private BSFMotor m_hoverMotor;
42
43 public BSActorHover(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_hoverMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorHover,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorHover,refresh", m_controllingPrim.LocalID);
69
70 // If not active any more, turn me off
71 if (!m_controllingPrim.HoverActive)
72 {
73 SetEnabled(false);
74 }
75
76 // If the object is physically active, add the hoverer prestep action
77 if (isActive)
78 {
79 ActivateHover();
80 }
81 else
82 {
83 DeactivateHover();
84 }
85 }
86
87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
88 // Register a prestep action to restore physical requirements before the next simulation step.
89 // Called at taint-time.
90 // BSActor.RemoveDependencies()
91 public override void RemoveDependencies()
92 {
93 // Nothing to do for the hoverer since it is all software at pre-step action time.
94 }
95
96 // If a hover motor has not been created, create one and start the hovering.
97 private void ActivateHover()
98 {
99 if (m_hoverMotor == null)
100 {
101 // Turning the target on
102 m_hoverMotor = new BSFMotor("BSActorHover",
103 m_controllingPrim.HoverTau, // timeScale
104 BSMotor.Infinite, // decay time scale
105 1f // efficiency
106 );
107 m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());
108 m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z);
109 m_hoverMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.
110
111 m_physicsScene.BeforeStep += Hoverer;
112 }
113 }
114
115 private void DeactivateHover()
116 {
117 if (m_hoverMotor != null)
118 {
119 m_physicsScene.BeforeStep -= Hoverer;
120 m_hoverMotor = null;
121 }
122 }
123
124 // Called just before the simulation step. Update the vertical position for hoverness.
125 private void Hoverer(float timeStep)
126 {
127 // Don't do hovering while the object is selected.
128 if (!isActive)
129 return;
130
131 m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z);
132 m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());
133 float targetHeight = m_hoverMotor.Step(timeStep);
134
135 // 'targetHeight' is where we'd like the Z of the prim to be at this moment.
136 // Compute the amount of force to push us there.
137 float moveForce = (targetHeight - m_controllingPrim.RawPosition.Z) * m_controllingPrim.RawMass;
138 // Undo anything the object thinks it's doing at the moment
139 moveForce = -m_controllingPrim.RawVelocity.Z * m_controllingPrim.Mass;
140
141 m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, new OMV.Vector3(0f, 0f, moveForce));
142 m_physicsScene.DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}",
143 m_controllingPrim.LocalID, targetHeight, moveForce, m_controllingPrim.RawMass);
144 }
145
146 // Based on current position, determine what we should be hovering at now.
147 // Must recompute often. What if we walked offa cliff>
148 private float ComputeCurrentHoverHeight()
149 {
150 float ret = m_controllingPrim.HoverHeight;
151 float groundHeight = m_physicsScene.TerrainManager.GetTerrainHeightAtXYZ(m_controllingPrim.RawPosition);
152
153 switch (m_controllingPrim.HoverType)
154 {
155 case PIDHoverType.Ground:
156 ret = groundHeight + m_controllingPrim.HoverHeight;
157 break;
158 case PIDHoverType.GroundAndWater:
159 float waterHeight = m_physicsScene.TerrainManager.GetWaterLevelAtXYZ(m_controllingPrim.RawPosition);
160 if (groundHeight > waterHeight)
161 {
162 ret = groundHeight + m_controllingPrim.HoverHeight;
163 }
164 else
165 {
166 ret = waterHeight + m_controllingPrim.HoverHeight;
167 }
168 break;
169 }
170 return ret;
171 }
172}
173}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
index 7219617..8b0fdeb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
@@ -36,11 +36,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37public class BSActorLockAxis : BSActor 37public class BSActorLockAxis : BSActor
38{ 38{
39 bool TryExperimentalLockAxisCode = true;
40 BSConstraint LockAxisConstraint = null; 39 BSConstraint LockAxisConstraint = null;
41 40
42 public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName) 41 public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName)
43 : base(physicsScene, pObj,actorName) 42 : base(physicsScene, pObj, actorName)
44 { 43 {
45 m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID); 44 m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID);
46 LockAxisConstraint = null; 45 LockAxisConstraint = null;
@@ -64,23 +63,18 @@ public class BSActorLockAxis : BSActor
64 // BSActor.Refresh() 63 // BSActor.Refresh()
65 public override void Refresh() 64 public override void Refresh()
66 { 65 {
67 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,lockedAxis={1},enabled={2},pActive={3}", 66 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,lockedAxis={1},enabled={2},pActive={3}",
68 m_controllingPrim.LocalID, m_controllingPrim.LockedAxis, Enabled, m_controllingPrim.IsPhysicallyActive); 67 m_controllingPrim.LocalID, m_controllingPrim.LockedAngularAxis, Enabled, m_controllingPrim.IsPhysicallyActive);
69 // If all the axis are free, we don't need to exist 68 // If all the axis are free, we don't need to exist
70 if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree) 69 if (m_controllingPrim.LockedAngularAxis == m_controllingPrim.LockedAxisFree)
71 { 70 {
72 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,allAxisFree,removing={1}", m_controllingPrim.LocalID, ActorName); 71 Enabled = false;
73 m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName);
74 return;
75 } 72 }
73
76 // If the object is physically active, add the axis locking constraint 74 // If the object is physically active, add the axis locking constraint
77 if (Enabled 75 if (isActive)
78 && m_controllingPrim.IsPhysicallyActive
79 && TryExperimentalLockAxisCode
80 && m_controllingPrim.LockedAxis != m_controllingPrim.LockedAxisFree)
81 { 76 {
82 if (LockAxisConstraint == null) 77 AddAxisLockConstraint();
83 AddAxisLockConstraint();
84 } 78 }
85 else 79 else
86 { 80 {
@@ -91,15 +85,15 @@ public class BSActorLockAxis : BSActor
91 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 85 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
92 // Register a prestep action to restore physical requirements before the next simulation step. 86 // Register a prestep action to restore physical requirements before the next simulation step.
93 // Called at taint-time. 87 // Called at taint-time.
94 // BSActor.RemoveBodyDependencies() 88 // BSActor.RemoveDependencies()
95 public override void RemoveBodyDependencies() 89 public override void RemoveDependencies()
96 { 90 {
97 if (LockAxisConstraint != null) 91 if (LockAxisConstraint != null)
98 { 92 {
99 // If a constraint is set up, remove it from the physical scene 93 // If a constraint is set up, remove it from the physical scene
100 RemoveAxisLockConstraint(); 94 RemoveAxisLockConstraint();
101 // Schedule a call before the next simulation step to restore the constraint. 95 // Schedule a call before the next simulation step to restore the constraint.
102 m_physicsScene.PostTaintObject(m_controllingPrim.LockedAxisActorName, m_controllingPrim.LocalID, delegate() 96 m_physicsScene.PostTaintObject("BSActorLockAxis:" + ActorName, m_controllingPrim.LocalID, delegate()
103 { 97 {
104 Refresh(); 98 Refresh();
105 }); 99 });
@@ -108,58 +102,76 @@ public class BSActorLockAxis : BSActor
108 102
109 private void AddAxisLockConstraint() 103 private void AddAxisLockConstraint()
110 { 104 {
111 // Lock that axis by creating a 6DOF constraint that has one end in the world and 105 if (LockAxisConstraint == null)
112 // the other in the object. 106 {
113 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817 107 // Lock that axis by creating a 6DOF constraint that has one end in the world and
114 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380 108 // the other in the object.
115 109 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
116 // Remove any existing axis constraint (just to be sure) 110 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
117 RemoveAxisLockConstraint();
118 111
119 BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(m_physicsScene.World, m_controllingPrim.PhysBody, 112 // Remove any existing axis constraint (just to be sure)
120 OMV.Vector3.Zero, OMV.Quaternion.Identity, 113 RemoveAxisLockConstraint();
121 false /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
122 LockAxisConstraint = axisConstrainer;
123 m_physicsScene.Constraints.AddConstraint(LockAxisConstraint);
124 114
125 // The constraint is tied to the world and oriented to the prim. 115 BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(m_physicsScene.World, m_controllingPrim.PhysBody,
116 OMV.Vector3.Zero, OMV.Quaternion.Identity,
117 false /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
118 LockAxisConstraint = axisConstrainer;
119 m_physicsScene.Constraints.AddConstraint(LockAxisConstraint);
126 120
127 // Free to move linearly in the region 121 // The constraint is tied to the world and oriented to the prim.
128 OMV.Vector3 linearLow = OMV.Vector3.Zero;
129 OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize;
130 axisConstrainer.SetLinearLimits(linearLow, linearHigh);
131 122
132 // Angular with some axis locked 123 // Free to move linearly in the region
133 float fPI = (float)Math.PI; 124 OMV.Vector3 linearLow = OMV.Vector3.Zero;
134 OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI); 125 OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize;
135 OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI); 126 if (m_controllingPrim.LockedLinearAxis.X != BSPhysObject.FreeAxis)
136 if (m_controllingPrim.LockedAxis.X != 1f) 127 {
137 { 128 linearLow.X = m_controllingPrim.RawPosition.X;
138 angularLow.X = 0f; 129 linearHigh.X = m_controllingPrim.RawPosition.X;
139 angularHigh.X = 0f; 130 }
140 } 131 if (m_controllingPrim.LockedLinearAxis.Y != BSPhysObject.FreeAxis)
141 if (m_controllingPrim.LockedAxis.Y != 1f) 132 {
142 { 133 linearLow.Y = m_controllingPrim.RawPosition.Y;
143 angularLow.Y = 0f; 134 linearHigh.Y = m_controllingPrim.RawPosition.Y;
144 angularHigh.Y = 0f; 135 }
145 } 136 if (m_controllingPrim.LockedLinearAxis.Z != BSPhysObject.FreeAxis)
146 if (m_controllingPrim.LockedAxis.Z != 1f) 137 {
147 { 138 linearLow.Z = m_controllingPrim.RawPosition.Z;
148 angularLow.Z = 0f; 139 linearHigh.Z = m_controllingPrim.RawPosition.Z;
149 angularHigh.Z = 0f; 140 }
150 } 141 axisConstrainer.SetLinearLimits(linearLow, linearHigh);
151 if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh)) 142
152 { 143 // Angular with some axis locked
153 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID); 144 float fPI = (float)Math.PI;
154 } 145 OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI);
146 OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI);
147 if (m_controllingPrim.LockedAngularAxis.X != BSPhysObject.FreeAxis)
148 {
149 angularLow.X = 0f;
150 angularHigh.X = 0f;
151 }
152 if (m_controllingPrim.LockedAngularAxis.Y != BSPhysObject.FreeAxis)
153 {
154 angularLow.Y = 0f;
155 angularHigh.Y = 0f;
156 }
157 if (m_controllingPrim.LockedAngularAxis.Z != BSPhysObject.FreeAxis)
158 {
159 angularLow.Z = 0f;
160 angularHigh.Z = 0f;
161 }
162 if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh))
163 {
164 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID);
165 }
155 166
156 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}", 167 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}",
157 m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh); 168 m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh);
158 169
159 // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo. 170 // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
160 axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f); 171 axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
161 172
162 axisConstrainer.RecomputeConstraintVariables(m_controllingPrim.RawMass); 173 axisConstrainer.RecomputeConstraintVariables(m_controllingPrim.RawMass);
174 }
163 } 175 }
164 176
165 private void RemoveAxisLockConstraint() 177 private void RemoveAxisLockConstraint()
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
new file mode 100755
index 0000000..bdf4bc0
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
@@ -0,0 +1,219 @@
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 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorMoveToTarget : BSActor
40{
41 private BSVMotor m_targetMotor;
42
43 public BSActorMoveToTarget(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_targetMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorMoveToTarget,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 // MoveToTarget only works on physical prims
54 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
55 }
56
57 // Release any connections and resources used by the actor.
58 // BSActor.Dispose()
59 public override void Dispose()
60 {
61 Enabled = false;
62 }
63
64 // Called when physical parameters (properties set in Bullet) need to be re-applied.
65 // Called at taint-time.
66 // BSActor.Refresh()
67 public override void Refresh()
68 {
69 m_physicsScene.DetailLog("{0},BSActorMoveToTarget,refresh,enabled={1},active={2},target={3},tau={4}",
70 m_controllingPrim.LocalID, Enabled, m_controllingPrim.MoveToTargetActive,
71 m_controllingPrim.MoveToTargetTarget, m_controllingPrim.MoveToTargetTau );
72
73 // If not active any more...
74 if (!m_controllingPrim.MoveToTargetActive)
75 {
76 Enabled = false;
77 }
78
79 if (isActive)
80 {
81 ActivateMoveToTarget();
82 }
83 else
84 {
85 DeactivateMoveToTarget();
86 }
87 }
88
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time.
92 // BSActor.RemoveDependencies()
93 public override void RemoveDependencies()
94 {
95 // Nothing to do for the moveToTarget since it is all software at pre-step action time.
96 }
97
98 // If a hover motor has not been created, create one and start the hovering.
99 private void ActivateMoveToTarget()
100 {
101 if (m_targetMotor == null)
102 {
103 // We're taking over after this.
104 m_controllingPrim.ZeroMotion(true);
105
106 /* Someday use the PID controller
107 m_targetMotor = new BSPIDVMotor("BSActorMoveToTarget-" + m_controllingPrim.LocalID.ToString());
108 m_targetMotor.TimeScale = m_controllingPrim.MoveToTargetTau;
109 m_targetMotor.Efficiency = 1f;
110 */
111 m_targetMotor = new BSVMotor("BSActorMoveToTarget-" + m_controllingPrim.LocalID.ToString(),
112 m_controllingPrim.MoveToTargetTau, // timeScale
113 BSMotor.Infinite, // decay time scale
114 1f // efficiency
115 );
116 m_targetMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.
117 m_targetMotor.SetTarget(m_controllingPrim.MoveToTargetTarget);
118 m_targetMotor.SetCurrent(m_controllingPrim.RawPosition);
119
120 // m_physicsScene.BeforeStep += Mover;
121 m_physicsScene.BeforeStep += Mover2;
122 }
123 else
124 {
125 // If already allocated, make sure the target and other paramters are current
126 m_targetMotor.SetTarget(m_controllingPrim.MoveToTargetTarget);
127 m_targetMotor.SetCurrent(m_controllingPrim.RawPosition);
128 }
129 }
130
131 private void DeactivateMoveToTarget()
132 {
133 if (m_targetMotor != null)
134 {
135 // m_physicsScene.BeforeStep -= Mover;
136 m_physicsScene.BeforeStep -= Mover2;
137 m_targetMotor = null;
138 }
139 }
140
141 // Origional mover that set the objects position to move to the target.
142 // The problem was that gravity would keep trying to push the object down so
143 // the overall downward velocity would increase to infinity.
144 // Called just before the simulation step.
145 private void Mover(float timeStep)
146 {
147 // Don't do hovering while the object is selected.
148 if (!isActive)
149 return;
150
151 OMV.Vector3 origPosition = m_controllingPrim.RawPosition; // DEBUG DEBUG (for printout below)
152
153 // 'movePosition' is where we'd like the prim to be at this moment.
154 OMV.Vector3 movePosition = m_controllingPrim.RawPosition + m_targetMotor.Step(timeStep);
155
156 // If we are very close to our target, turn off the movement motor.
157 if (m_targetMotor.ErrorIsZero())
158 {
159 m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover,zeroMovement,movePos={1},pos={2},mass={3}",
160 m_controllingPrim.LocalID, movePosition, m_controllingPrim.RawPosition, m_controllingPrim.Mass);
161 m_controllingPrim.ForcePosition = m_targetMotor.TargetValue;
162 m_controllingPrim.ForceVelocity = OMV.Vector3.Zero;
163 // Setting the position does not cause the physics engine to generate a property update. Force it.
164 m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
165 }
166 else
167 {
168 m_controllingPrim.ForcePosition = movePosition;
169 // Setting the position does not cause the physics engine to generate a property update. Force it.
170 m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
171 }
172 m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover,move,fromPos={1},movePos={2}",
173 m_controllingPrim.LocalID, origPosition, movePosition);
174 }
175
176 // Version of mover that applies forces to move the physical object to the target.
177 // Also overcomes gravity so the object doesn't just drop to the ground.
178 // Called just before the simulation step.
179 private void Mover2(float timeStep)
180 {
181 // Don't do hovering while the object is selected.
182 if (!isActive)
183 return;
184
185 OMV.Vector3 origPosition = m_controllingPrim.RawPosition; // DEBUG DEBUG (for printout below)
186 OMV.Vector3 addedForce = OMV.Vector3.Zero;
187
188 // CorrectionVector is the movement vector required this step
189 OMV.Vector3 correctionVector = m_targetMotor.Step(timeStep, m_controllingPrim.RawPosition);
190
191 // If we are very close to our target, turn off the movement motor.
192 if (m_targetMotor.ErrorIsZero())
193 {
194 m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover3,zeroMovement,pos={1},mass={2}",
195 m_controllingPrim.LocalID, m_controllingPrim.RawPosition, m_controllingPrim.Mass);
196 m_controllingPrim.ForcePosition = m_targetMotor.TargetValue;
197 m_controllingPrim.ForceVelocity = OMV.Vector3.Zero;
198 // Setting the position does not cause the physics engine to generate a property update. Force it.
199 m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
200 }
201 else
202 {
203 // First force to move us there -- the motor return a timestep scaled value.
204 addedForce = correctionVector / timeStep;
205 // Remove the existing velocity (only the moveToTarget force counts)
206 addedForce -= m_controllingPrim.RawVelocity;
207 // Overcome gravity.
208 addedForce -= m_controllingPrim.Gravity;
209
210 // Add enough force to overcome the mass of the object
211 addedForce *= m_controllingPrim.Mass;
212
213 m_controllingPrim.AddForce(addedForce, false /* pushForce */, true /* inTaintTime */);
214 }
215 m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover3,move,fromPos={1},addedForce={2}",
216 m_controllingPrim.LocalID, origPosition, addedForce);
217 }
218}
219}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
new file mode 100755
index 0000000..96fa0b6
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
@@ -0,0 +1,137 @@
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 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorSetForce : BSActor
40{
41 BSFMotor m_forceMotor;
42
43 public BSActorSetForce(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_forceMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorSetForce,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorSetForce,refresh", m_controllingPrim.LocalID);
69
70 // If not active any more, get rid of me (shouldn't ever happen, but just to be safe)
71 if (m_controllingPrim.RawForce == OMV.Vector3.Zero)
72 {
73 m_physicsScene.DetailLog("{0},BSActorSetForce,refresh,notSetForce,removing={1}", m_controllingPrim.LocalID, ActorName);
74 Enabled = false;
75 return;
76 }
77
78 // If the object is physically active, add the hoverer prestep action
79 if (isActive)
80 {
81 ActivateSetForce();
82 }
83 else
84 {
85 DeactivateSetForce();
86 }
87 }
88
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time.
92 // BSActor.RemoveDependencies()
93 public override void RemoveDependencies()
94 {
95 // Nothing to do for the hoverer since it is all software at pre-step action time.
96 }
97
98 // If a hover motor has not been created, create one and start the hovering.
99 private void ActivateSetForce()
100 {
101 if (m_forceMotor == null)
102 {
103 // A fake motor that might be used someday
104 m_forceMotor = new BSFMotor("setForce", 1f, 1f, 1f);
105
106 m_physicsScene.BeforeStep += Mover;
107 }
108 }
109
110 private void DeactivateSetForce()
111 {
112 if (m_forceMotor != null)
113 {
114 m_physicsScene.BeforeStep -= Mover;
115 m_forceMotor = null;
116 }
117 }
118
119 // Called just before the simulation step. Update the vertical position for hoverness.
120 private void Mover(float timeStep)
121 {
122 // Don't do force while the object is selected.
123 if (!isActive)
124 return;
125
126 m_physicsScene.DetailLog("{0},BSActorSetForce,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawForce);
127 if (m_controllingPrim.PhysBody.HasPhysicalBody)
128 {
129 m_physicsScene.PE.ApplyCentralForce(m_controllingPrim.PhysBody, m_controllingPrim.RawForce);
130 m_controllingPrim.ActivateIfPhysical(false);
131 }
132
133 // TODO:
134 }
135}
136}
137
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
new file mode 100755
index 0000000..65098e1
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
@@ -0,0 +1,138 @@
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 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorSetTorque : BSActor
40{
41 BSFMotor m_torqueMotor;
42
43 public BSActorSetTorque(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_torqueMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorSetTorque,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,torque={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque);
69
70 // If not active any more, get rid of me (shouldn't ever happen, but just to be safe)
71 if (m_controllingPrim.RawTorque == OMV.Vector3.Zero)
72 {
73 m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,notSetTorque,disabling={1}", m_controllingPrim.LocalID, ActorName);
74 Enabled = false;
75 return;
76 }
77
78 // If the object is physically active, add the hoverer prestep action
79 if (isActive)
80 {
81 ActivateSetTorque();
82 }
83 else
84 {
85 DeactivateSetTorque();
86 }
87 }
88
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time.
92 // BSActor.RemoveDependencies()
93 public override void RemoveDependencies()
94 {
95 // Nothing to do for the hoverer since it is all software at pre-step action time.
96 }
97
98 // If a hover motor has not been created, create one and start the hovering.
99 private void ActivateSetTorque()
100 {
101 if (m_torqueMotor == null)
102 {
103 // A fake motor that might be used someday
104 m_torqueMotor = new BSFMotor("setTorque", 1f, 1f, 1f);
105
106 m_physicsScene.BeforeStep += Mover;
107 }
108 }
109
110 private void DeactivateSetTorque()
111 {
112 if (m_torqueMotor != null)
113 {
114 m_physicsScene.BeforeStep -= Mover;
115 m_torqueMotor = null;
116 }
117 }
118
119 // Called just before the simulation step. Update the vertical position for hoverness.
120 private void Mover(float timeStep)
121 {
122 // Don't do force while the object is selected.
123 if (!isActive)
124 return;
125
126 m_physicsScene.DetailLog("{0},BSActorSetTorque,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque);
127 if (m_controllingPrim.PhysBody.HasPhysicalBody)
128 {
129 m_controllingPrim.AddAngularForce(m_controllingPrim.RawTorque, false, true);
130 m_controllingPrim.ActivateIfPhysical(false);
131 }
132
133 // TODO:
134 }
135}
136}
137
138
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
index 5a19ba4..e0ccc50 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
@@ -32,56 +32,79 @@ namespace OpenSim.Region.Physics.BulletSPlugin
32{ 32{
33public class BSActorCollection 33public class BSActorCollection
34{ 34{
35 private BSScene PhysicsScene { get; set; } 35 private BSScene m_physicsScene { get; set; }
36 private Dictionary<string, BSActor> m_actors; 36 private Dictionary<string, BSActor> m_actors;
37 37
38 public BSActorCollection(BSScene physicsScene) 38 public BSActorCollection(BSScene physicsScene)
39 { 39 {
40 PhysicsScene = physicsScene; 40 m_physicsScene = physicsScene;
41 m_actors = new Dictionary<string, BSActor>(); 41 m_actors = new Dictionary<string, BSActor>();
42 } 42 }
43 public void Add(string name, BSActor actor) 43 public void Add(string name, BSActor actor)
44 { 44 {
45 m_actors[name] = actor; 45 lock (m_actors)
46 {
47 if (!m_actors.ContainsKey(name))
48 {
49 m_actors[name] = actor;
50 }
51 }
46 } 52 }
47 public bool RemoveAndRelease(string name) 53 public bool RemoveAndRelease(string name)
48 { 54 {
49 bool ret = false; 55 bool ret = false;
50 if (m_actors.ContainsKey(name)) 56 lock (m_actors)
51 { 57 {
52 BSActor beingRemoved = m_actors[name]; 58 if (m_actors.ContainsKey(name))
53 beingRemoved.Dispose(); 59 {
54 m_actors.Remove(name); 60 BSActor beingRemoved = m_actors[name];
55 ret = true; 61 m_actors.Remove(name);
62 beingRemoved.Dispose();
63 ret = true;
64 }
56 } 65 }
57 return ret; 66 return ret;
58 } 67 }
59 public void Clear() 68 public void Clear()
60 { 69 {
61 Release(); 70 lock (m_actors)
62 m_actors.Clear(); 71 {
72 ForEachActor(a => a.Dispose());
73 m_actors.Clear();
74 }
75 }
76 public void Dispose()
77 {
78 Clear();
63 } 79 }
64 public bool HasActor(string name) 80 public bool HasActor(string name)
65 { 81 {
66 return m_actors.ContainsKey(name); 82 return m_actors.ContainsKey(name);
67 } 83 }
84 public bool TryGetActor(string actorName, out BSActor theActor)
85 {
86 return m_actors.TryGetValue(actorName, out theActor);
87 }
68 public void ForEachActor(Action<BSActor> act) 88 public void ForEachActor(Action<BSActor> act)
69 { 89 {
70 foreach (KeyValuePair<string, BSActor> kvp in m_actors) 90 lock (m_actors)
71 act(kvp.Value); 91 {
92 foreach (KeyValuePair<string, BSActor> kvp in m_actors)
93 act(kvp.Value);
94 }
72 } 95 }
73 96
74 public void Release() 97 public void Enable(bool enabl)
75 { 98 {
76 ForEachActor(a => a.Dispose()); 99 ForEachActor(a => a.SetEnabled(enabl));
77 } 100 }
78 public void Refresh() 101 public void Refresh()
79 { 102 {
80 ForEachActor(a => a.Refresh()); 103 ForEachActor(a => a.Refresh());
81 } 104 }
82 public void RemoveBodyDependencies() 105 public void RemoveDependencies()
83 { 106 {
84 ForEachActor(a => a.RemoveBodyDependencies()); 107 ForEachActor(a => a.RemoveDependencies());
85 } 108 }
86} 109}
87 110
@@ -90,7 +113,7 @@ public class BSActorCollection
90/// Each physical object can have 'actors' who are pushing the object around. 113/// Each physical object can have 'actors' who are pushing the object around.
91/// This can be used for hover, locking axis, making vehicles, etc. 114/// This can be used for hover, locking axis, making vehicles, etc.
92/// Each physical object can have multiple actors acting on it. 115/// Each physical object can have multiple actors acting on it.
93/// 116///
94/// An actor usually registers itself with physics scene events (pre-step action) 117/// An actor usually registers itself with physics scene events (pre-step action)
95/// and modifies the parameters on the host physical object. 118/// and modifies the parameters on the host physical object.
96/// </summary> 119/// </summary>
@@ -98,7 +121,7 @@ public abstract class BSActor
98{ 121{
99 protected BSScene m_physicsScene { get; private set; } 122 protected BSScene m_physicsScene { get; private set; }
100 protected BSPhysObject m_controllingPrim { get; private set; } 123 protected BSPhysObject m_controllingPrim { get; private set; }
101 protected bool Enabled { get; set; } 124 public virtual bool Enabled { get; set; }
102 public string ActorName { get; private set; } 125 public string ActorName { get; private set; }
103 126
104 public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName) 127 public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName)
@@ -114,8 +137,10 @@ public abstract class BSActor
114 { 137 {
115 get { return Enabled; } 138 get { return Enabled; }
116 } 139 }
117 // Turn the actor on an off. 140
118 public virtual void Enable(bool setEnabled) 141 // Turn the actor on an off. Only used by ActorCollection to set all enabled/disabled.
142 // Anyone else should assign true/false to 'Enabled'.
143 public void SetEnabled(bool setEnabled)
119 { 144 {
120 Enabled = setEnabled; 145 Enabled = setEnabled;
121 } 146 }
@@ -125,7 +150,7 @@ public abstract class BSActor
125 public abstract void Refresh(); 150 public abstract void Refresh();
126 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 151 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
127 // Register a prestep action to restore physical requirements before the next simulation step. 152 // Register a prestep action to restore physical requirements before the next simulation step.
128 public abstract void RemoveBodyDependencies(); 153 public abstract void RemoveDependencies();
129 154
130} 155}
131} 156}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index d0d9f34..be6f152 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -43,7 +43,9 @@ public enum ConstraintType : int
43 SLIDER_CONSTRAINT_TYPE, 43 SLIDER_CONSTRAINT_TYPE,
44 CONTACT_CONSTRAINT_TYPE, 44 CONTACT_CONSTRAINT_TYPE,
45 D6_SPRING_CONSTRAINT_TYPE, 45 D6_SPRING_CONSTRAINT_TYPE,
46 MAX_CONSTRAINT_TYPE 46 MAX_CONSTRAINT_TYPE, // last type defined by Bullet
47 //
48 FIXED_CONSTRAINT_TYPE = 1234 // BulletSim constraint that is fixed and unmoving
47} 49}
48 50
49// =============================================================================== 51// ===============================================================================
@@ -70,6 +72,8 @@ public enum BSPhysicsShapeType
70 SHAPE_COMPOUND = 22, 72 SHAPE_COMPOUND = 22,
71 SHAPE_HEIGHTMAP = 23, 73 SHAPE_HEIGHTMAP = 23,
72 SHAPE_AVATAR = 24, 74 SHAPE_AVATAR = 24,
75 SHAPE_CONVEXHULL= 25,
76 SHAPE_GIMPACT = 26,
73}; 77};
74 78
75// The native shapes have predefined shape hash keys 79// The native shapes have predefined shape hash keys
@@ -245,7 +249,7 @@ public enum CollisionFlags : uint
245 BS_VEHICLE_COLLISIONS = 1 << 12, // return collisions for vehicle ground checking 249 BS_VEHICLE_COLLISIONS = 1 << 12, // return collisions for vehicle ground checking
246 BS_RETURN_ROOT_COMPOUND_SHAPE = 1 << 13, // return the pos/rot of the root shape in a compound shape 250 BS_RETURN_ROOT_COMPOUND_SHAPE = 1 << 13, // return the pos/rot of the root shape in a compound shape
247 BS_NONE = 0, 251 BS_NONE = 0,
248 BS_ALL = 0xFFFFFFFF 252 BS_ALL = 0x7FFF // collision flags are a signed short
249}; 253};
250 254
251// Values f collisions groups and masks 255// Values f collisions groups and masks
@@ -261,14 +265,14 @@ public enum CollisionFilterGroups : uint
261 BDebrisGroup = 1 << 3, // 0008 265 BDebrisGroup = 1 << 3, // 0008
262 BSensorTrigger = 1 << 4, // 0010 266 BSensorTrigger = 1 << 4, // 0010
263 BCharacterGroup = 1 << 5, // 0020 267 BCharacterGroup = 1 << 5, // 0020
264 BAllGroup = 0x000FFFFF, 268 BAllGroup = 0x0007FFF, // collision flags are a signed short
265 // Filter groups defined by BulletSim 269 // Filter groups defined by BulletSim
266 BGroundPlaneGroup = 1 << 10, // 0400 270 BGroundPlaneGroup = 1 << 8, // 0400
267 BTerrainGroup = 1 << 11, // 0800 271 BTerrainGroup = 1 << 9, // 0800
268 BRaycastGroup = 1 << 12, // 1000 272 BRaycastGroup = 1 << 10, // 1000
269 BSolidGroup = 1 << 13, // 2000 273 BSolidGroup = 1 << 11, // 2000
270 // BLinksetGroup = xx // a linkset proper is either static or dynamic 274 // BLinksetGroup = xx // a linkset proper is either static or dynamic
271 BLinksetChildGroup = 1 << 14, // 4000 275 BLinksetChildGroup = 1 << 12, // 4000
272}; 276};
273 277
274// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 278// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
@@ -288,7 +292,7 @@ public enum ConstraintParamAxis : int
288 AXIS_ANGULAR_X, 292 AXIS_ANGULAR_X,
289 AXIS_ANGULAR_Y, 293 AXIS_ANGULAR_Y,
290 AXIS_ANGULAR_Z, 294 AXIS_ANGULAR_Z,
291 AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls 295 AXIS_LINEAR_ALL = 20, // added by BulletSim so we don't have to do zillions of calls
292 AXIS_ANGULAR_ALL, 296 AXIS_ANGULAR_ALL,
293 AXIS_ALL 297 AXIS_ALL
294}; 298};
@@ -297,7 +301,7 @@ public abstract class BSAPITemplate
297{ 301{
298// Returns the name of the underlying Bullet engine 302// Returns the name of the underlying Bullet engine
299public abstract string BulletEngineName { get; } 303public abstract string BulletEngineName { get; }
300public abstract string BulletEngineVersion { get; protected set;} 304public abstract string BulletEngineVersion { get; protected set;}
301 305
302// Initialization and simulation 306// Initialization and simulation
303public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, 307public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
@@ -320,11 +324,21 @@ public abstract BulletShape CreateMeshShape(BulletWorld world,
320 int indicesCount, int[] indices, 324 int indicesCount, int[] indices,
321 int verticesCount, float[] vertices ); 325 int verticesCount, float[] vertices );
322 326
327public abstract BulletShape CreateGImpactShape(BulletWorld world,
328 int indicesCount, int[] indices,
329 int verticesCount, float[] vertices );
330
323public abstract BulletShape CreateHullShape(BulletWorld world, 331public abstract BulletShape CreateHullShape(BulletWorld world,
324 int hullCount, float[] hulls); 332 int hullCount, float[] hulls);
325 333
326public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape, HACDParams parms); 334public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape, HACDParams parms);
327 335
336public abstract BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape);
337
338public abstract BulletShape CreateConvexHullShape(BulletWorld world,
339 int indicesCount, int[] indices,
340 int verticesCount, float[] vertices );
341
328public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData); 342public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData);
329 343
330public abstract bool IsNativeShape(BulletShape shape); 344public abstract bool IsNativeShape(BulletShape shape);
@@ -366,7 +380,7 @@ public abstract void DestroyObject(BulletWorld sim, BulletBody obj);
366// ===================================================================================== 380// =====================================================================================
367public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin); 381public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin);
368 382
369public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, 383public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
370 float scaleFactor, float collisionMargin); 384 float scaleFactor, float collisionMargin);
371 385
372// ===================================================================================== 386// =====================================================================================
@@ -381,7 +395,7 @@ public abstract BulletConstraint Create6DofConstraintToPoint(BulletWorld world,
381 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 395 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
382 396
383public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1, 397public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1,
384 Vector3 frameInBloc, Quaternion frameInBrot, 398 Vector3 frameInBloc, Quaternion frameInBrot,
385 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies); 399 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies);
386 400
387public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, 401public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
@@ -429,6 +443,38 @@ public abstract bool TranslationalLimitMotor(BulletConstraint constrain, float e
429 443
430public abstract bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold); 444public abstract bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold);
431 445
446public const int HINGE_NOT_SPECIFIED = -1;
447public abstract bool HingeSetLimits(BulletConstraint constrain, float low, float high, float softness, float bias, float relaxation);
448
449public abstract bool SpringEnable(BulletConstraint constrain, int index, float numericTrueFalse);
450
451public const int SPRING_NOT_SPECIFIED = -1;
452public abstract bool SpringSetEquilibriumPoint(BulletConstraint constrain, int index, float equilibriumPoint);
453
454public abstract bool SpringSetStiffness(BulletConstraint constrain, int index, float stiffnesss);
455
456public abstract bool SpringSetDamping(BulletConstraint constrain, int index, float damping);
457
458public const int SLIDER_LOWER_LIMIT = 0;
459public const int SLIDER_UPPER_LIMIT = 1;
460public const int SLIDER_LINEAR = 2;
461public const int SLIDER_ANGULAR = 3;
462public abstract bool SliderSetLimits(BulletConstraint constrain, int lowerUpper, int linAng, float val);
463
464public const int SLIDER_SET_SOFTNESS = 4;
465public const int SLIDER_SET_RESTITUTION = 5;
466public const int SLIDER_SET_DAMPING = 6;
467public const int SLIDER_SET_DIRECTION = 7;
468public const int SLIDER_SET_LIMIT = 8;
469public const int SLIDER_SET_ORTHO = 9;
470public abstract bool SliderSet(BulletConstraint constrain, int softRestDamp, int dirLimOrtho, int linAng, float val);
471
472public abstract bool SliderMotorEnable(BulletConstraint constrain, int linAng, float numericTrueFalse);
473
474public const int SLIDER_MOTOR_VELOCITY = 10;
475public const int SLIDER_MAX_MOTOR_FORCE = 11;
476public abstract bool SliderMotor(BulletConstraint constrain, int forceVel, int linAng, float val);
477
432public abstract bool CalculateTransforms(BulletConstraint constrain); 478public abstract bool CalculateTransforms(BulletConstraint constrain);
433 479
434public abstract bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); 480public abstract bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
@@ -452,6 +498,8 @@ public abstract bool AddObjectToWorld(BulletWorld world, BulletBody obj);
452 498
453public abstract bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj); 499public abstract bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj);
454 500
501public abstract bool ClearCollisionProxyCache(BulletWorld world, BulletBody obj);
502
455public abstract bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects); 503public abstract bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects);
456 504
457public abstract bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain); 505public abstract bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 25be416..fc18960 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -43,15 +43,10 @@ public sealed class BSCharacter : BSPhysObject
43 private OMV.Vector3 _size; 43 private OMV.Vector3 _size;
44 private bool _grabbed; 44 private bool _grabbed;
45 private bool _selected; 45 private bool _selected;
46 private OMV.Vector3 _position;
47 private float _mass; 46 private float _mass;
48 private float _avatarVolume; 47 private float _avatarVolume;
49 private OMV.Vector3 _force;
50 private OMV.Vector3 _velocity;
51 private OMV.Vector3 _torque;
52 private float _collisionScore; 48 private float _collisionScore;
53 private OMV.Vector3 _acceleration; 49 private OMV.Vector3 _acceleration;
54 private OMV.Quaternion _orientation;
55 private int _physicsActorType; 50 private int _physicsActorType;
56 private bool _isPhysical; 51 private bool _isPhysical;
57 private bool _flying; 52 private bool _flying;
@@ -61,31 +56,26 @@ public sealed class BSCharacter : BSPhysObject
61 private OMV.Vector3 _rotationalVelocity; 56 private OMV.Vector3 _rotationalVelocity;
62 private bool _kinematic; 57 private bool _kinematic;
63 private float _buoyancy; 58 private float _buoyancy;
64 private bool _isStationaryStanding; // true is standing on a stationary object
65 59
66 private BSVMotor _velocityMotor; 60 private BSActorAvatarMove m_moveActor;
61 private const string AvatarMoveActorName = "BSCharacter.AvatarMove";
67 62
68 private OMV.Vector3 _PIDTarget; 63 private OMV.Vector3 _PIDTarget;
69 private bool _usePID; 64 private bool _usePID;
70 private float _PIDTau; 65 private float _PIDTau;
71 private bool _useHoverPID;
72 private float _PIDHoverHeight;
73 private PIDHoverType _PIDHoverType;
74 private float _PIDHoverTao;
75 66
76 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) 67 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
77 : base(parent_scene, localID, avName, "BSCharacter") 68 : base(parent_scene, localID, avName, "BSCharacter")
78 { 69 {
79 _physicsActorType = (int)ActorTypes.Agent; 70 _physicsActorType = (int)ActorTypes.Agent;
80 _position = pos; 71 RawPosition = pos;
81 72
82 _flying = isFlying; 73 _flying = isFlying;
83 _orientation = OMV.Quaternion.Identity; 74 RawOrientation = OMV.Quaternion.Identity;
84 _velocity = OMV.Vector3.Zero; 75 RawVelocity = OMV.Vector3.Zero;
85 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 76 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
86 Friction = BSParam.AvatarStandingFriction; 77 Friction = BSParam.AvatarStandingFriction;
87 Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor; 78 Density = BSParam.AvatarDensity;
88 _isStationaryStanding = false;
89 79
90 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 80 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
91 // replace with the default values. 81 // replace with the default values.
@@ -99,19 +89,26 @@ public sealed class BSCharacter : BSPhysObject
99 // set _avatarVolume and _mass based on capsule size, _density and Scale 89 // set _avatarVolume and _mass based on capsule size, _density and Scale
100 ComputeAvatarVolumeAndMass(); 90 ComputeAvatarVolumeAndMass();
101 91
102 SetupMovementMotor(); 92 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5},pos={6}",
103 93 LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos);
104 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
105 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
106 94
107 // do actual creation in taint time 95 // do actual creation in taint time
108 PhysicsScene.TaintedObject("BSCharacter.create", delegate() 96 PhysScene.TaintedObject(LocalID, "BSCharacter.create", delegate()
109 { 97 {
110 DetailLog("{0},BSCharacter.create,taint", LocalID); 98 DetailLog("{0},BSCharacter.create,taint", LocalID);
111 // New body and shape into PhysBody and PhysShape 99 // New body and shape into PhysBody and PhysShape
112 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this); 100 PhysScene.Shapes.GetBodyAndShape(true, PhysScene.World, this);
101
102 // The avatar's movement is controlled by this motor that speeds up and slows down
103 // the avatar seeking to reach the motor's target speed.
104 // This motor runs as a prestep action for the avatar so it will keep the avatar
105 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
106 m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName);
107 PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
113 108
114 SetPhysicalProperties(); 109 SetPhysicalProperties();
110
111 IsInitialized = true;
115 }); 112 });
116 return; 113 return;
117 } 114 }
@@ -119,219 +116,68 @@ public sealed class BSCharacter : BSPhysObject
119 // called when this character is being destroyed and the resources should be released 116 // called when this character is being destroyed and the resources should be released
120 public override void Destroy() 117 public override void Destroy()
121 { 118 {
119 IsInitialized = false;
120
122 base.Destroy(); 121 base.Destroy();
123 122
124 DetailLog("{0},BSCharacter.Destroy", LocalID); 123 DetailLog("{0},BSCharacter.Destroy", LocalID);
125 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 124 PhysScene.TaintedObject(LocalID, "BSCharacter.destroy", delegate()
126 { 125 {
127 PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */); 126 PhysScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
128 PhysBody.Clear(); 127 PhysBody.Clear();
129 PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */); 128 PhysShape.Dereference(PhysScene);
130 PhysShape.Clear(); 129 PhysShape = new BSShapeNull();
131 }); 130 });
132 } 131 }
133 132
134 private void SetPhysicalProperties() 133 private void SetPhysicalProperties()
135 { 134 {
136 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 135 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
137 136
138 ZeroMotion(true); 137 ZeroMotion(true);
139 ForcePosition = _position; 138 ForcePosition = RawPosition;
140 139
141 // Set the velocity 140 // Set the velocity
142 _velocityMotor.Reset(); 141 if (m_moveActor != null)
143 _velocityMotor.SetTarget(_velocity); 142 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false);
144 _velocityMotor.SetCurrent(_velocity); 143
145 ForceVelocity = _velocity; 144 ForceVelocity = RawVelocity;
146 145
147 // This will enable or disable the flying buoyancy of the avatar. 146 // This will enable or disable the flying buoyancy of the avatar.
148 // Needs to be reset especially when an avatar is recreated after crossing a region boundry. 147 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
149 Flying = _flying; 148 Flying = _flying;
150 149
151 PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution); 150 PhysScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution);
152 PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin); 151 PhysScene.PE.SetMargin(PhysShape.physShapeInfo, PhysScene.Params.collisionMargin);
153 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); 152 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
154 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 153 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
155 if (BSParam.CcdMotionThreshold > 0f) 154 if (BSParam.CcdMotionThreshold > 0f)
156 { 155 {
157 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 156 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
158 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 157 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
159 } 158 }
160 159
161 UpdatePhysicalMassProperties(RawMass, false); 160 UpdatePhysicalMassProperties(RawMass, false);
162 161
163 // Make so capsule does not fall over 162 // Make so capsule does not fall over
164 PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); 163 PhysScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
164
165 // The avatar mover sets some parameters.
166 PhysicalActors.Refresh();
165 167
166 PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); 168 PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
167 169
168 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 170 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
169 171
170 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); 172 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
171 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION); 173 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION);
172 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); 174 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
173 175
174 // Do this after the object has been added to the world 176 // Do this after the object has been added to the world
175 PhysBody.collisionType = CollisionType.Avatar; 177 PhysBody.collisionType = CollisionType.Avatar;
176 PhysBody.ApplyCollisionMask(PhysicsScene); 178 PhysBody.ApplyCollisionMask(PhysScene);
177 }
178
179 // The avatar's movement is controlled by this motor that speeds up and slows down
180 // the avatar seeking to reach the motor's target speed.
181 // This motor runs as a prestep action for the avatar so it will keep the avatar
182 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
183 private void SetupMovementMotor()
184 {
185 // Infinite decay and timescale values so motor only changes current to target values.
186 _velocityMotor = new BSVMotor("BSCharacter.Velocity",
187 0.2f, // time scale
188 BSMotor.Infinite, // decay time scale
189 BSMotor.InfiniteVector, // friction timescale
190 1f // efficiency
191 );
192 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
193
194 RegisterPreStepAction("BSCharactor.Movement", LocalID, delegate(float timeStep)
195 {
196 // TODO: Decide if the step parameters should be changed depending on the avatar's
197 // state (flying, colliding, ...). There is code in ODE to do this.
198
199 // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
200 // specified for the avatar is the one that should be used. For falling, if the avatar
201 // is not flying and is not colliding then it is presumed to be falling and the Z
202 // component is not fooled with (thus allowing gravity to do its thing).
203 // When the avatar is standing, though, the user has specified a velocity of zero and
204 // the avatar should be standing. But if the avatar is pushed by something in the world
205 // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
206 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
207 // errors can creap in and the avatar will slowly float off in some direction.
208 // So, the problem is that, when an avatar is standing, we cannot tell creaping error
209 // from real pushing.
210 // The code below uses whether the collider is static or moving to decide whether to zero motion.
211
212 _velocityMotor.Step(timeStep);
213 _isStationaryStanding = false;
214
215 // If we're not supposed to be moving, make sure things are zero.
216 if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero)
217 {
218 // The avatar shouldn't be moving
219 _velocityMotor.Zero();
220
221 if (IsColliding)
222 {
223 // If we are colliding with a stationary object, presume we're standing and don't move around
224 if (!ColliderIsMoving)
225 {
226 DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID);
227 _isStationaryStanding = true;
228 ZeroMotion(true /* inTaintTime */);
229 }
230
231 // Standing has more friction on the ground
232 if (Friction != BSParam.AvatarStandingFriction)
233 {
234 Friction = BSParam.AvatarStandingFriction;
235 PhysicsScene.PE.SetFriction(PhysBody, Friction);
236 }
237 }
238 else
239 {
240 if (Flying)
241 {
242 // Flying and not collising and velocity nearly zero.
243 ZeroMotion(true /* inTaintTime */);
244 }
245 }
246
247 DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding);
248 }
249 else
250 {
251 // Supposed to be moving.
252 OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue;
253
254 if (Friction != BSParam.AvatarFriction)
255 {
256 // Probably starting up walking. Set friction to moving friction.
257 Friction = BSParam.AvatarFriction;
258 PhysicsScene.PE.SetFriction(PhysBody, Friction);
259 }
260
261 // If falling, we keep the world's downward vector no matter what the other axis specify.
262 // The check for _velocity.Z < 0 makes jumping work (temporary upward force).
263 if (!Flying && !IsColliding)
264 {
265 if (_velocity.Z < 0)
266 stepVelocity.Z = _velocity.Z;
267 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
268 }
269
270 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
271 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass;
272
273 // Should we check for move force being small and forcing velocity to zero?
274
275 // Add special movement force to allow avatars to walk up stepped surfaces.
276 moveForce += WalkUpStairs();
277
278 DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
279 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
280 }
281 });
282 } 179 }
283 180
284 // Decide if the character is colliding with a low object and compute a force to pop the
285 // avatar up so it can walk up and over the low objects.
286 private OMV.Vector3 WalkUpStairs()
287 {
288 OMV.Vector3 ret = OMV.Vector3.Zero;
289
290 // This test is done if moving forward, not flying and is colliding with something.
291 // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
292 // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
293 if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
294 {
295 // The range near the character's feet where we will consider stairs
296 float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
297 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
298
299 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is
300 foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList)
301 {
302 // Don't care about collisions with the terrain
303 if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID)
304 {
305 OMV.Vector3 touchPosition = kvp.Value.Position;
306 // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
307 // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
308 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
309 {
310 // This contact is within the 'near the feet' range.
311 // The normal should be our contact point to the object so it is pointing away
312 // thus the difference between our facing orientation and the normal should be small.
313 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation;
314 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
315 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
316 if (diff < BSParam.AvatarStepApproachFactor)
317 {
318 // Found the stairs contact point. Push up a little to raise the character.
319 float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor;
320 ret = new OMV.Vector3(0f, 0f, upForce);
321
322 // Also move the avatar up for the new height
323 OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
324 ForcePosition = RawPosition + displacement;
325 }
326 DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
327 LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
328 }
329 }
330 }
331 }
332
333 return ret;
334 }
335 181
336 public override void RequestPhysicsterseUpdate() 182 public override void RequestPhysicsterseUpdate()
337 { 183 {
@@ -348,6 +194,10 @@ public sealed class BSCharacter : BSPhysObject
348 } 194 }
349 195
350 set { 196 set {
197 // This is how much the avatar size is changing. Positive means getting bigger.
198 // The avatar altitude must be adjusted for this change.
199 float heightChange = value.Z - _size.Z;
200
351 _size = value; 201 _size = value;
352 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 202 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
353 // replace with the default values. 203 // replace with the default values.
@@ -359,14 +209,18 @@ public sealed class BSCharacter : BSPhysObject
359 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", 209 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
360 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 210 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
361 211
362 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() 212 PhysScene.TaintedObject(LocalID, "BSCharacter.setSize", delegate()
363 { 213 {
364 if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape) 214 if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
365 { 215 {
366 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); 216 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
367 UpdatePhysicalMassProperties(RawMass, true); 217 UpdatePhysicalMassProperties(RawMass, true);
218
219 // Adjust the avatar's position to account for the increase/decrease in size
220 ForcePosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, RawPosition.Z + heightChange / 2f);
221
368 // Make sure this change appears as a property update event 222 // Make sure this change appears as a property update event
369 PhysicsScene.PE.PushUpdate(PhysBody); 223 PhysScene.PE.PushUpdate(PhysBody);
370 } 224 }
371 }); 225 });
372 226
@@ -377,11 +231,6 @@ public sealed class BSCharacter : BSPhysObject
377 { 231 {
378 set { BaseShape = value; } 232 set { BaseShape = value; }
379 } 233 }
380 // I want the physics engine to make an avatar capsule
381 public override BSPhysicsShapeType PreferredPhysicalShape
382 {
383 get {return BSPhysicsShapeType.SHAPE_CAPSULE; }
384 }
385 234
386 public override bool Grabbed { 235 public override bool Grabbed {
387 set { _grabbed = value; } 236 set { _grabbed = value; }
@@ -403,29 +252,29 @@ public sealed class BSCharacter : BSPhysObject
403 // Called at taint time! 252 // Called at taint time!
404 public override void ZeroMotion(bool inTaintTime) 253 public override void ZeroMotion(bool inTaintTime)
405 { 254 {
406 _velocity = OMV.Vector3.Zero; 255 RawVelocity = OMV.Vector3.Zero;
407 _acceleration = OMV.Vector3.Zero; 256 _acceleration = OMV.Vector3.Zero;
408 _rotationalVelocity = OMV.Vector3.Zero; 257 _rotationalVelocity = OMV.Vector3.Zero;
409 258
410 // Zero some other properties directly into the physics engine 259 // Zero some other properties directly into the physics engine
411 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 260 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
412 { 261 {
413 if (PhysBody.HasPhysicalBody) 262 if (PhysBody.HasPhysicalBody)
414 PhysicsScene.PE.ClearAllForces(PhysBody); 263 PhysScene.PE.ClearAllForces(PhysBody);
415 }); 264 });
416 } 265 }
417 public override void ZeroAngularMotion(bool inTaintTime) 266 public override void ZeroAngularMotion(bool inTaintTime)
418 { 267 {
419 _rotationalVelocity = OMV.Vector3.Zero; 268 _rotationalVelocity = OMV.Vector3.Zero;
420 269
421 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 270 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
422 { 271 {
423 if (PhysBody.HasPhysicalBody) 272 if (PhysBody.HasPhysicalBody)
424 { 273 {
425 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero); 274 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero);
426 PhysicsScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero); 275 PhysScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero);
427 // The next also get rid of applied linear force but the linear velocity is untouched. 276 // The next also get rid of applied linear force but the linear velocity is untouched.
428 PhysicsScene.PE.ClearForces(PhysBody); 277 PhysScene.PE.ClearForces(PhysBody);
429 } 278 }
430 }); 279 });
431 } 280 }
@@ -433,38 +282,33 @@ public sealed class BSCharacter : BSPhysObject
433 282
434 public override void LockAngularMotion(OMV.Vector3 axis) { return; } 283 public override void LockAngularMotion(OMV.Vector3 axis) { return; }
435 284
436 public override OMV.Vector3 RawPosition
437 {
438 get { return _position; }
439 set { _position = value; }
440 }
441 public override OMV.Vector3 Position { 285 public override OMV.Vector3 Position {
442 get { 286 get {
443 // Don't refetch the position because this function is called a zillion times 287 // Don't refetch the position because this function is called a zillion times
444 // _position = PhysicsScene.PE.GetObjectPosition(Scene.World, LocalID); 288 // RawPosition = PhysicsScene.PE.GetObjectPosition(Scene.World, LocalID);
445 return _position; 289 return RawPosition;
446 } 290 }
447 set { 291 set {
448 _position = value; 292 RawPosition = value;
449 293
450 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 294 PhysScene.TaintedObject(LocalID, "BSCharacter.setPosition", delegate()
451 { 295 {
452 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 296 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
453 PositionSanityCheck(); 297 PositionSanityCheck();
454 ForcePosition = _position; 298 ForcePosition = RawPosition;
455 }); 299 });
456 } 300 }
457 } 301 }
458 public override OMV.Vector3 ForcePosition { 302 public override OMV.Vector3 ForcePosition {
459 get { 303 get {
460 _position = PhysicsScene.PE.GetPosition(PhysBody); 304 RawPosition = PhysScene.PE.GetPosition(PhysBody);
461 return _position; 305 return RawPosition;
462 } 306 }
463 set { 307 set {
464 _position = value; 308 RawPosition = value;
465 if (PhysBody.HasPhysicalBody) 309 if (PhysBody.HasPhysicalBody)
466 { 310 {
467 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 311 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
468 } 312 }
469 } 313 }
470 } 314 }
@@ -478,30 +322,30 @@ public sealed class BSCharacter : BSPhysObject
478 bool ret = false; 322 bool ret = false;
479 323
480 // TODO: check for out of bounds 324 // TODO: check for out of bounds
481 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) 325 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
482 { 326 {
483 // The character is out of the known/simulated area. 327 // The character is out of the known/simulated area.
484 // Force the avatar position to be within known. ScenePresence will use the position 328 // Force the avatar position to be within known. ScenePresence will use the position
485 // plus the velocity to decide if the avatar is moving out of the region. 329 // plus the velocity to decide if the avatar is moving out of the region.
486 RawPosition = PhysicsScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition); 330 RawPosition = PhysScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition);
487 DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition); 331 DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition);
488 return true; 332 return true;
489 } 333 }
490 334
491 // If below the ground, move the avatar up 335 // If below the ground, move the avatar up
492 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); 336 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
493 if (Position.Z < terrainHeight) 337 if (Position.Z < terrainHeight)
494 { 338 {
495 DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight); 339 DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight);
496 _position.Z = terrainHeight + BSParam.AvatarBelowGroundUpCorrectionMeters; 340 RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, terrainHeight + BSParam.AvatarBelowGroundUpCorrectionMeters);
497 ret = true; 341 ret = true;
498 } 342 }
499 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 343 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
500 { 344 {
501 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); 345 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
502 if (Position.Z < waterHeight) 346 if (Position.Z < waterHeight)
503 { 347 {
504 _position.Z = waterHeight; 348 RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, waterHeight);
505 ret = true; 349 ret = true;
506 } 350 }
507 } 351 }
@@ -519,10 +363,10 @@ public sealed class BSCharacter : BSPhysObject
519 { 363 {
520 // The new position value must be pushed into the physics engine but we can't 364 // The new position value must be pushed into the physics engine but we can't
521 // just assign to "Position" because of potential call loops. 365 // just assign to "Position" because of potential call loops.
522 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() 366 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.PositionSanityCheck", delegate()
523 { 367 {
524 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 368 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
525 ForcePosition = _position; 369 ForcePosition = RawPosition;
526 }); 370 });
527 ret = true; 371 ret = true;
528 } 372 }
@@ -532,25 +376,25 @@ public sealed class BSCharacter : BSPhysObject
532 public override float Mass { get { return _mass; } } 376 public override float Mass { get { return _mass; } }
533 377
534 // used when we only want this prim's mass and not the linkset thing 378 // used when we only want this prim's mass and not the linkset thing
535 public override float RawMass { 379 public override float RawMass {
536 get {return _mass; } 380 get {return _mass; }
537 } 381 }
538 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) 382 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
539 { 383 {
540 OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); 384 OMV.Vector3 localInertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
541 PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia); 385 PhysScene.PE.SetMassProps(PhysBody, physMass, localInertia);
542 } 386 }
543 387
544 public override OMV.Vector3 Force { 388 public override OMV.Vector3 Force {
545 get { return _force; } 389 get { return RawForce; }
546 set { 390 set {
547 _force = value; 391 RawForce = value;
548 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 392 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
549 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() 393 PhysScene.TaintedObject(LocalID, "BSCharacter.SetForce", delegate()
550 { 394 {
551 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); 395 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
552 if (PhysBody.HasPhysicalBody) 396 if (PhysBody.HasPhysicalBody)
553 PhysicsScene.PE.SetObjectForce(PhysBody, _force); 397 PhysScene.PE.SetObjectForce(PhysBody, RawForce);
554 }); 398 });
555 } 399 }
556 } 400 }
@@ -564,6 +408,7 @@ public sealed class BSCharacter : BSPhysObject
564 408
565 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 409 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
566 public override void SetVolumeDetect(int param) { return; } 410 public override void SetVolumeDetect(int param) { return; }
411 public override bool IsVolumeDetect { get { return false; } }
567 412
568 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } 413 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
569 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } 414 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
@@ -573,61 +418,49 @@ public sealed class BSCharacter : BSPhysObject
573 { 418 {
574 get 419 get
575 { 420 {
576 return m_targetVelocity; 421 return base.m_targetVelocity;
577 } 422 }
578 set 423 set
579 { 424 {
580 DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value); 425 DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value);
581 m_targetVelocity = value; 426 m_targetVelocity = value;
582 OMV.Vector3 targetVel = value; 427 OMV.Vector3 targetVel = value;
583 if (_setAlwaysRun) 428 if (_setAlwaysRun && !_flying)
584 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f); 429 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f);
585 430
586 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() 431 if (m_moveActor != null)
587 { 432 m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */);
588 _velocityMotor.Reset();
589 _velocityMotor.SetTarget(targetVel);
590 _velocityMotor.SetCurrent(_velocity);
591 _velocityMotor.Enabled = true;
592 });
593 } 433 }
594 } 434 }
595 public override OMV.Vector3 RawVelocity
596 {
597 get { return _velocity; }
598 set { _velocity = value; }
599 }
600 // Directly setting velocity means this is what the user really wants now. 435 // Directly setting velocity means this is what the user really wants now.
601 public override OMV.Vector3 Velocity { 436 public override OMV.Vector3 Velocity {
602 get { return _velocity; } 437 get { return RawVelocity; }
603 set { 438 set {
604 _velocity = value; 439 RawVelocity = value;
605 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 440 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity);
606 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 441 PhysScene.TaintedObject(LocalID, "BSCharacter.setVelocity", delegate()
607 { 442 {
608 _velocityMotor.Reset(); 443 if (m_moveActor != null)
609 _velocityMotor.SetCurrent(_velocity); 444 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */);
610 _velocityMotor.SetTarget(_velocity);
611 _velocityMotor.Enabled = false;
612 445
613 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 446 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, RawVelocity);
614 ForceVelocity = _velocity; 447 ForceVelocity = RawVelocity;
615 }); 448 });
616 } 449 }
617 } 450 }
618 public override OMV.Vector3 ForceVelocity { 451 public override OMV.Vector3 ForceVelocity {
619 get { return _velocity; } 452 get { return RawVelocity; }
620 set { 453 set {
621 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); 454 PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity");
622 455
623 _velocity = value; 456 RawVelocity = value;
624 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); 457 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
625 PhysicsScene.PE.Activate(PhysBody, true); 458 PhysScene.PE.Activate(PhysBody, true);
626 } 459 }
627 } 460 }
628 public override OMV.Vector3 Torque { 461 public override OMV.Vector3 Torque {
629 get { return _torque; } 462 get { return RawTorque; }
630 set { _torque = value; 463 set { RawTorque = value;
631 } 464 }
632 } 465 }
633 public override float CollisionScore { 466 public override float CollisionScore {
@@ -639,22 +472,27 @@ public sealed class BSCharacter : BSPhysObject
639 get { return _acceleration; } 472 get { return _acceleration; }
640 set { _acceleration = value; } 473 set { _acceleration = value; }
641 } 474 }
642 public override OMV.Quaternion RawOrientation
643 {
644 get { return _orientation; }
645 set { _orientation = value; }
646 }
647 public override OMV.Quaternion Orientation { 475 public override OMV.Quaternion Orientation {
648 get { return _orientation; } 476 get { return RawOrientation; }
649 set { 477 set {
650 // Orientation is set zillions of times when an avatar is walking. It's like 478 // Orientation is set zillions of times when an avatar is walking. It's like
651 // the viewer doesn't trust us. 479 // the viewer doesn't trust us.
652 if (_orientation != value) 480 if (RawOrientation != value)
653 { 481 {
654 _orientation = value; 482 RawOrientation = value;
655 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() 483 PhysScene.TaintedObject(LocalID, "BSCharacter.setOrientation", delegate()
656 { 484 {
657 ForceOrientation = _orientation; 485 // Bullet assumes we know what we are doing when forcing orientation
486 // so it lets us go against all the rules and just compensates for them later.
487 // This forces rotation to be only around the Z axis and doesn't change any of the other axis.
488 // This keeps us from flipping the capsule over which the veiwer does not understand.
489 float oRoll, oPitch, oYaw;
490 RawOrientation.GetEulerAngles(out oRoll, out oPitch, out oYaw);
491 OMV.Quaternion trimmedOrientation = OMV.Quaternion.CreateFromEulers(0f, 0f, oYaw);
492 // DetailLog("{0},BSCharacter.setOrientation,taint,val={1},valDir={2},conv={3},convDir={4}",
493 // LocalID, RawOrientation, OMV.Vector3.UnitX * RawOrientation,
494 // trimmedOrientation, OMV.Vector3.UnitX * trimmedOrientation);
495 ForceOrientation = trimmedOrientation;
658 }); 496 });
659 } 497 }
660 } 498 }
@@ -664,16 +502,16 @@ public sealed class BSCharacter : BSPhysObject
664 { 502 {
665 get 503 get
666 { 504 {
667 _orientation = PhysicsScene.PE.GetOrientation(PhysBody); 505 RawOrientation = PhysScene.PE.GetOrientation(PhysBody);
668 return _orientation; 506 return RawOrientation;
669 } 507 }
670 set 508 set
671 { 509 {
672 _orientation = value; 510 RawOrientation = value;
673 if (PhysBody.HasPhysicalBody) 511 if (PhysBody.HasPhysicalBody)
674 { 512 {
675 // _position = PhysicsScene.PE.GetPosition(BSBody); 513 // RawPosition = PhysicsScene.PE.GetPosition(BSBody);
676 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 514 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
677 } 515 }
678 } 516 }
679 } 517 }
@@ -722,14 +560,14 @@ public sealed class BSCharacter : BSPhysObject
722 public override bool FloatOnWater { 560 public override bool FloatOnWater {
723 set { 561 set {
724 _floatOnWater = value; 562 _floatOnWater = value;
725 PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() 563 PhysScene.TaintedObject(LocalID, "BSCharacter.setFloatOnWater", delegate()
726 { 564 {
727 if (PhysBody.HasPhysicalBody) 565 if (PhysBody.HasPhysicalBody)
728 { 566 {
729 if (_floatOnWater) 567 if (_floatOnWater)
730 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 568 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
731 else 569 else
732 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 570 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
733 } 571 }
734 }); 572 });
735 } 573 }
@@ -750,7 +588,7 @@ public sealed class BSCharacter : BSPhysObject
750 public override float Buoyancy { 588 public override float Buoyancy {
751 get { return _buoyancy; } 589 get { return _buoyancy; }
752 set { _buoyancy = value; 590 set { _buoyancy = value;
753 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() 591 PhysScene.TaintedObject(LocalID, "BSCharacter.setBuoyancy", delegate()
754 { 592 {
755 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 593 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
756 ForceBuoyancy = _buoyancy; 594 ForceBuoyancy = _buoyancy;
@@ -759,8 +597,8 @@ public sealed class BSCharacter : BSPhysObject
759 } 597 }
760 public override float ForceBuoyancy { 598 public override float ForceBuoyancy {
761 get { return _buoyancy; } 599 get { return _buoyancy; }
762 set { 600 set {
763 PhysicsScene.AssertInTaintTime("BSCharacter.ForceBuoyancy"); 601 PhysScene.AssertInTaintTime("BSCharacter.ForceBuoyancy");
764 602
765 _buoyancy = value; 603 _buoyancy = value;
766 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 604 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
@@ -768,7 +606,7 @@ public sealed class BSCharacter : BSPhysObject
768 float grav = BSParam.Gravity * (1f - _buoyancy); 606 float grav = BSParam.Gravity * (1f - _buoyancy);
769 Gravity = new OMV.Vector3(0f, 0f, grav); 607 Gravity = new OMV.Vector3(0f, 0f, grav);
770 if (PhysBody.HasPhysicalBody) 608 if (PhysBody.HasPhysicalBody)
771 PhysicsScene.PE.SetGravity(PhysBody, Gravity); 609 PhysScene.PE.SetGravity(PhysBody, Gravity);
772 } 610 }
773 } 611 }
774 612
@@ -783,46 +621,25 @@ public sealed class BSCharacter : BSPhysObject
783 set { _PIDTau = value; } 621 set { _PIDTau = value; }
784 } 622 }
785 623
786 // Used for llSetHoverHeight and maybe vehicle height
787 // Hover Height will override MoveTo target's Z
788 public override bool PIDHoverActive {
789 set { _useHoverPID = value; }
790 }
791 public override float PIDHoverHeight {
792 set { _PIDHoverHeight = value; }
793 }
794 public override PIDHoverType PIDHoverType {
795 set { _PIDHoverType = value; }
796 }
797 public override float PIDHoverTau {
798 set { _PIDHoverTao = value; }
799 }
800
801 // For RotLookAt
802 public override OMV.Quaternion APIDTarget { set { return; } }
803 public override bool APIDActive { set { return; } }
804 public override float APIDStrength { set { return; } }
805 public override float APIDDamping { set { return; } }
806
807 public override void AddForce(OMV.Vector3 force, bool pushforce) 624 public override void AddForce(OMV.Vector3 force, bool pushforce)
808 { 625 {
809 // Since this force is being applied in only one step, make this a force per second. 626 // Since this force is being applied in only one step, make this a force per second.
810 OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep; 627 OMV.Vector3 addForce = force / PhysScene.LastTimeStep;
811 AddForce(addForce, pushforce, false); 628 AddForce(addForce, pushforce, false);
812 } 629 }
813 private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 630 public override void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
814 if (force.IsFinite()) 631 if (force.IsFinite())
815 { 632 {
816 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 633 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
817 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); 634 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce);
818 635
819 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() 636 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.AddForce", delegate()
820 { 637 {
821 // Bullet adds this central force to the total force for this tick 638 // Bullet adds this central force to the total force for this tick
822 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce); 639 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
823 if (PhysBody.HasPhysicalBody) 640 if (PhysBody.HasPhysicalBody)
824 { 641 {
825 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 642 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
826 } 643 }
827 }); 644 });
828 } 645 }
@@ -833,7 +650,7 @@ public sealed class BSCharacter : BSPhysObject
833 } 650 }
834 } 651 }
835 652
836 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 653 public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
837 } 654 }
838 public override void SetMomentum(OMV.Vector3 momentum) { 655 public override void SetMomentum(OMV.Vector3 momentum) {
839 } 656 }
@@ -841,14 +658,14 @@ public sealed class BSCharacter : BSPhysObject
841 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size) 658 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size)
842 { 659 {
843 OMV.Vector3 newScale; 660 OMV.Vector3 newScale;
844 661
845 // Bullet's capsule total height is the "passed height + radius * 2"; 662 // Bullet's capsule total height is the "passed height + radius * 2";
846 // The base capsule is 1 diameter and 2 height (passed radius=0.5, passed height = 1) 663 // The base capsule is 1 unit in diameter and 2 units in height (passed radius=0.5, passed height = 1)
847 // The number we pass in for 'scaling' is the multiplier to get that base 664 // The number we pass in for 'scaling' is the multiplier to get that base
848 // shape to be the size desired. 665 // shape to be the size desired.
849 // So, when creating the scale for the avatar height, we take the passed height 666 // So, when creating the scale for the avatar height, we take the passed height
850 // (size.Z) and remove the caps. 667 // (size.Z) and remove the caps.
851 // Another oddity of the Bullet capsule implementation is that it presumes the Y 668 // An oddity of the Bullet capsule implementation is that it presumes the Y
852 // dimension is the radius of the capsule. Even though some of the code allows 669 // dimension is the radius of the capsule. Even though some of the code allows
853 // for a asymmetrical capsule, other parts of the code presume it is cylindrical. 670 // for a asymmetrical capsule, other parts of the code presume it is cylindrical.
854 671
@@ -856,12 +673,36 @@ public sealed class BSCharacter : BSPhysObject
856 newScale.X = size.X / 2f; 673 newScale.X = size.X / 2f;
857 newScale.Y = size.Y / 2f; 674 newScale.Y = size.Y / 2f;
858 675
676 float heightAdjust = BSParam.AvatarHeightMidFudge;
677 if (BSParam.AvatarHeightLowFudge != 0f || BSParam.AvatarHeightHighFudge != 0f)
678 {
679 const float AVATAR_LOW = 1.1f;
680 const float AVATAR_MID = 1.775f; // 1.87f
681 const float AVATAR_HI = 2.45f;
682 // An avatar is between 1.1 and 2.45 meters. Midpoint is 1.775m.
683 float midHeightOffset = size.Z - AVATAR_MID;
684 if (midHeightOffset < 0f)
685 {
686 // Small avatar. Add the adjustment based on the distance from midheight
687 heightAdjust += ((-1f * midHeightOffset) / (AVATAR_MID - AVATAR_LOW)) * BSParam.AvatarHeightLowFudge;
688 }
689 else
690 {
691 // Large avatar. Add the adjustment based on the distance from midheight
692 heightAdjust += ((midHeightOffset) / (AVATAR_HI - AVATAR_MID)) * BSParam.AvatarHeightHighFudge;
693 }
694 }
859 // The total scale height is the central cylindar plus the caps on the two ends. 695 // The total scale height is the central cylindar plus the caps on the two ends.
860 newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2)) / 2f; 696 newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2) + heightAdjust) / 2f;
697 // m_log.DebugFormat("{0} ComputeAvatarScale: size={1},adj={2},scale={3}", LogHeader, size, heightAdjust, newScale);
698
861 // If smaller than the endcaps, just fake like we're almost that small 699 // If smaller than the endcaps, just fake like we're almost that small
862 if (newScale.Z < 0) 700 if (newScale.Z < 0)
863 newScale.Z = 0.1f; 701 newScale.Z = 0.1f;
864 702
703 DetailLog("{0},BSCharacter.ComputerAvatarScale,size={1},lowF={2},midF={3},hiF={4},adj={5},newScale={6}",
704 LocalID, size, BSParam.AvatarHeightLowFudge, BSParam.AvatarHeightMidFudge, BSParam.AvatarHeightHighFudge, heightAdjust, newScale);
705
865 return newScale; 706 return newScale;
866 } 707 }
867 708
@@ -886,18 +727,18 @@ public sealed class BSCharacter : BSPhysObject
886 // the world that things have changed. 727 // the world that things have changed.
887 public override void UpdateProperties(EntityProperties entprop) 728 public override void UpdateProperties(EntityProperties entprop)
888 { 729 {
889 // Don't change position if standing on a stationary object. 730 // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
890 if (!_isStationaryStanding) 731 TriggerPreUpdatePropertyAction(ref entprop);
891 _position = entprop.Position;
892 732
893 _orientation = entprop.Rotation; 733 RawPosition = entprop.Position;
734 RawOrientation = entprop.Rotation;
894 735
895 // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar 736 // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar
896 // and will send agent updates to the clients if velocity changes by more than 737 // and will send agent updates to the clients if velocity changes by more than
897 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many 738 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many
898 // extra updates. 739 // extra updates.
899 if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f)) 740 if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f))
900 _velocity = entprop.Velocity; 741 RawVelocity = entprop.Velocity;
901 742
902 _acceleration = entprop.Acceleration; 743 _acceleration = entprop.Acceleration;
903 _rotationalVelocity = entprop.RotationalVelocity; 744 _rotationalVelocity = entprop.RotationalVelocity;
@@ -905,8 +746,8 @@ public sealed class BSCharacter : BSPhysObject
905 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. 746 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
906 if (PositionSanityCheck(true)) 747 if (PositionSanityCheck(true))
907 { 748 {
908 DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position); 749 DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, RawPosition);
909 entprop.Position = _position; 750 entprop.Position = RawPosition;
910 } 751 }
911 752
912 // remember the current and last set values 753 // remember the current and last set values
@@ -917,10 +758,10 @@ public sealed class BSCharacter : BSPhysObject
917 // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); 758 // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
918 759
919 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 760 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
920 // base.RequestPhysicsterseUpdate(); 761 // PhysScene.PostUpdate(this);
921 762
922 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 763 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
923 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 764 LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity);
924 } 765 }
925} 766}
926} 767}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 42b5c49..b47e9a8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -64,7 +64,7 @@ public abstract class BSConstraint : IDisposable
64 { 64 {
65 bool success = PhysicsScene.PE.DestroyConstraint(m_world, m_constraint); 65 bool success = PhysicsScene.PE.DestroyConstraint(m_world, m_constraint);
66 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}",
67 BSScene.DetailLogZero, 67 m_body1.ID,
68 m_body1.ID, m_body1.AddrString, 68 m_body1.ID, m_body1.AddrString,
69 m_body2.ID, m_body2.AddrString, 69 m_body2.ID, m_body2.AddrString,
70 success); 70 success);
@@ -77,7 +77,10 @@ public abstract class BSConstraint : IDisposable
77 { 77 {
78 bool ret = false; 78 bool ret = false;
79 if (m_enabled) 79 if (m_enabled)
80 {
81 m_world.physicsScene.DetailLog("{0},BSConstraint.SetLinearLimits,taint,low={1},high={2}", m_body1.ID, low, high);
80 ret = PhysicsScene.PE.SetLinearLimits(m_constraint, low, high); 82 ret = PhysicsScene.PE.SetLinearLimits(m_constraint, low, high);
83 }
81 return ret; 84 return ret;
82 } 85 }
83 86
@@ -86,6 +89,7 @@ public abstract class BSConstraint : IDisposable
86 bool ret = false; 89 bool ret = false;
87 if (m_enabled) 90 if (m_enabled)
88 { 91 {
92 m_world.physicsScene.DetailLog("{0},BSConstraint.SetAngularLimits,taint,low={1},high={2}", m_body1.ID, low, high);
89 ret = PhysicsScene.PE.SetAngularLimits(m_constraint, low, high); 93 ret = PhysicsScene.PE.SetAngularLimits(m_constraint, low, high);
90 } 94 }
91 return ret; 95 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
index d0949f5..7fcb75c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
@@ -32,12 +32,19 @@ using OpenMetaverse;
32namespace OpenSim.Region.Physics.BulletSPlugin 32namespace OpenSim.Region.Physics.BulletSPlugin
33{ 33{
34 34
35public sealed class BSConstraint6Dof : BSConstraint 35public class BSConstraint6Dof : BSConstraint
36{ 36{
37 private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; 37 private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]";
38 38
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 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2) :base(world)
42 {
43 m_body1 = obj1;
44 m_body2 = obj2;
45 m_enabled = false;
46 }
47
41 // Create a btGeneric6DofConstraint 48 // Create a btGeneric6DofConstraint
42 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2, 49 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
43 Vector3 frame1, Quaternion frame1rot, 50 Vector3 frame1, Quaternion frame1rot,
@@ -52,9 +59,11 @@ public sealed class BSConstraint6Dof : BSConstraint
52 frame2, frame2rot, 59 frame2, frame2rot,
53 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); 60 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
54 m_enabled = true; 61 m_enabled = true;
55 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", 62 PhysicsScene.DetailLog("{0},BS6DofConstraint,create,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
56 BSScene.DetailLogZero, world.worldID, 63 m_body1.ID, world.worldID,
57 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); 64 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
65 PhysicsScene.DetailLog("{0},BS6DofConstraint,create, f1Loc={1},f1Rot={2},f2Loc={3},f2Rot={4},usefA={5},disCol={6}",
66 m_body1.ID, frame1, frame1rot, frame2, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
58 } 67 }
59 68
60 // 6 Dof constraint based on a midpoint between the two constrained bodies 69 // 6 Dof constraint based on a midpoint between the two constrained bodies
@@ -79,9 +88,11 @@ public sealed class BSConstraint6Dof : BSConstraint
79 m_constraint = PhysicsScene.PE.Create6DofConstraintToPoint(m_world, m_body1, m_body2, 88 m_constraint = PhysicsScene.PE.Create6DofConstraintToPoint(m_world, m_body1, m_body2,
80 joinPoint, 89 joinPoint,
81 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); 90 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
91
82 PhysicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", 92 PhysicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
83 BSScene.DetailLogZero, world.worldID, m_constraint.AddrString, 93 m_body1.ID, world.worldID, m_constraint.AddrString,
84 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); 94 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
95
85 if (!m_constraint.HasPhysicalConstraint) 96 if (!m_constraint.HasPhysicalConstraint)
86 { 97 {
87 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", 98 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
@@ -106,8 +117,10 @@ public sealed class BSConstraint6Dof : BSConstraint
106 frameInBloc, frameInBrot, 117 frameInBloc, frameInBrot,
107 useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies); 118 useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies);
108 m_enabled = true; 119 m_enabled = true;
109 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFixed,wID={1},rID={2},rBody={3}", 120 PhysicsScene.DetailLog("{0},BS6DofConstraint,createFixed,wID={1},rID={2},rBody={3}",
110 BSScene.DetailLogZero, world.worldID, obj1.ID, obj1.AddrString); 121 m_body1.ID, world.worldID, obj1.ID, obj1.AddrString);
122 PhysicsScene.DetailLog("{0},BS6DofConstraint,createFixed, fBLoc={1},fBRot={2},usefA={3},disCol={4}",
123 m_body1.ID, frameInBloc, frameInBrot, useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies);
111 } 124 }
112 125
113 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) 126 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs
new file mode 100755
index 0000000..7a76a9a
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs
@@ -0,0 +1,54 @@
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 OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraintConeTwist : BSConstraint
36{
37 public override ConstraintType Type { get { return ConstraintType.CONETWIST_CONSTRAINT_TYPE; } }
38
39 public BSConstraintConeTwist(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 frameInAloc, Quaternion frameInArot,
41 Vector3 frameInBloc, Quaternion frameInBrot,
42 bool disableCollisionsBetweenLinkedBodies)
43 : base(world)
44 {
45 m_body1 = obj1;
46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateConeTwistConstraint(world, obj1, obj2,
48 frameInAloc, frameInArot, frameInBloc, frameInBrot,
49 disableCollisionsBetweenLinkedBodies);
50 m_enabled = true;
51 }
52}
53
54}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
index 7714a03..ed89f63 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
@@ -45,7 +45,7 @@ public sealed class BSConstraintHinge : BSConstraint
45 m_body1 = obj1; 45 m_body1 = obj1;
46 m_body2 = obj2; 46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2, 47 m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2,
48 pivotInA, pivotInB, axisInA, axisInB, 48 pivotInA, pivotInB, axisInA, axisInB,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); 49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
50 m_enabled = true; 50 m_enabled = true;
51 } 51 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs
new file mode 100755
index 0000000..37cfa07
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs
@@ -0,0 +1,55 @@
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 OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraintSlider : BSConstraint
36{
37 public override ConstraintType Type { get { return ConstraintType.SLIDER_CONSTRAINT_TYPE; } }
38
39 public BSConstraintSlider(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 frameInAloc, Quaternion frameInArot,
41 Vector3 frameInBloc, Quaternion frameInBrot,
42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
43 : base(world)
44 {
45 m_body1 = obj1;
46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateSliderConstraint(world, obj1, obj2,
48 frameInAloc, frameInArot, frameInBloc, frameInBrot,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
50 m_enabled = true;
51 }
52
53}
54
55}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs
new file mode 100755
index 0000000..8e7ddff
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs
@@ -0,0 +1,103 @@
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 OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraintSpring : BSConstraint6Dof
36{
37 public override ConstraintType Type { get { return ConstraintType.D6_SPRING_CONSTRAINT_TYPE; } }
38
39 public BSConstraintSpring(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 frame1Loc, Quaternion frame1Rot,
41 Vector3 frame2Loc, Quaternion frame2Rot,
42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
43 :base(world, obj1, obj2)
44 {
45 m_constraint = PhysicsScene.PE.Create6DofSpringConstraint(world, obj1, obj2,
46 frame1Loc, frame1Rot, frame2Loc, frame2Rot,
47 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
48 m_enabled = true;
49
50 PhysicsScene.DetailLog("{0},BSConstraintSpring,create,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
51 obj1.ID, world.worldID, obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
52 PhysicsScene.DetailLog("{0},BSConstraintSpring,create, f1Loc={1},f1Rot={2},f2Loc={3},f2Rot={4},usefA={5},disCol={6}",
53 m_body1.ID, frame1Loc, frame1Rot, frame2Loc, frame2Rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
54 }
55
56 public bool SetAxisEnable(int pIndex, bool pAxisEnable)
57 {
58 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEnable,obj1ID={1},obj2ID={2},indx={3},enable={4}",
59 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pAxisEnable);
60 PhysicsScene.PE.SpringEnable(m_constraint, pIndex, BSParam.NumericBool(pAxisEnable));
61 return true;
62 }
63
64 public bool SetStiffness(int pIndex, float pStiffness)
65 {
66 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetStiffness,obj1ID={1},obj2ID={2},indx={3},stiff={4}",
67 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pStiffness);
68 PhysicsScene.PE.SpringSetStiffness(m_constraint, pIndex, pStiffness);
69 return true;
70 }
71
72 public bool SetDamping(int pIndex, float pDamping)
73 {
74 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetDamping,obj1ID={1},obj2ID={2},indx={3},damp={4}",
75 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pDamping);
76 PhysicsScene.PE.SpringSetDamping(m_constraint, pIndex, pDamping);
77 return true;
78 }
79
80 public bool SetEquilibriumPoint(int pIndex, float pEqPoint)
81 {
82 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEquilibriumPoint,obj1ID={1},obj2ID={2},indx={3},eqPoint={4}",
83 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pEqPoint);
84 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, pIndex, pEqPoint);
85 return true;
86 }
87
88 public bool SetEquilibriumPoint(Vector3 linearEq, Vector3 angularEq)
89 {
90 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEquilibriumPoint,obj1ID={1},obj2ID={2},linearEq={3},angularEq={4}",
91 m_body1.ID, m_body1.ID, m_body2.ID, linearEq, angularEq);
92 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 0, linearEq.X);
93 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 1, linearEq.Y);
94 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 2, linearEq.Z);
95 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 3, angularEq.X);
96 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 4, angularEq.Y);
97 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 5, angularEq.Z);
98 return true;
99 }
100
101}
102
103} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 0fd1f73..7b98f9d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
45 private static string LogHeader = "[BULLETSIM VEHICLE]"; 45 private static string LogHeader = "[BULLETSIM VEHICLE]";
46 46
47 // the prim this dynamic controller belongs to 47 // the prim this dynamic controller belongs to
48 private BSPrim ControllingPrim { get; set; } 48 private BSPrimLinkable ControllingPrim { get; set; }
49 49
50 private bool m_haveRegisteredForSceneEvents; 50 private bool m_haveRegisteredForSceneEvents;
51 51
@@ -125,33 +125,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
125 static readonly float PIOverFour = ((float)Math.PI) / 4f; 125 static readonly float PIOverFour = ((float)Math.PI) / 4f;
126 static readonly float PIOverTwo = ((float)Math.PI) / 2f; 126 static readonly float PIOverTwo = ((float)Math.PI) / 2f;
127 127
128 // For debugging, flags to turn on and off individual corrections.
129 public bool enableAngularVerticalAttraction;
130 public bool enableAngularDeflection;
131 public bool enableAngularBanking;
132
133 public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) 128 public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName)
134 : base(myScene, myPrim, actorName) 129 : base(myScene, myPrim, actorName)
135 { 130 {
136 ControllingPrim = myPrim;
137 Type = Vehicle.TYPE_NONE; 131 Type = Vehicle.TYPE_NONE;
138 m_haveRegisteredForSceneEvents = false; 132 m_haveRegisteredForSceneEvents = false;
139 SetupVehicleDebugging();
140 }
141 133
142 // Stopgap debugging enablement. Allows source level debugging but still checking 134 ControllingPrim = myPrim as BSPrimLinkable;
143 // in changes by making enablement of debugging flags from INI file. 135 if (ControllingPrim == null)
144 public void SetupVehicleDebugging()
145 {
146 enableAngularVerticalAttraction = true;
147 enableAngularDeflection = false;
148 enableAngularBanking = true;
149 if (BSParam.VehicleDebuggingEnabled)
150 { 136 {
151 enableAngularVerticalAttraction = true; 137 // THIS CANNOT HAPPEN!!
152 enableAngularDeflection = false;
153 enableAngularBanking = false;
154 } 138 }
139 VDetailLog("{0},Creation", ControllingPrim.LocalID);
155 } 140 }
156 141
157 // Return 'true' if this vehicle is doing vehicle things 142 // Return 'true' if this vehicle is doing vehicle things
@@ -173,7 +158,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
173 switch (pParam) 158 switch (pParam)
174 { 159 {
175 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 160 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
176 m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); 161 m_angularDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
177 break; 162 break;
178 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: 163 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
179 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); 164 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -209,7 +194,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
209 m_VhoverTimescale = Math.Max(pValue, 0.01f); 194 m_VhoverTimescale = Math.Max(pValue, 0.01f);
210 break; 195 break;
211 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: 196 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
212 m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); 197 m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
213 break; 198 break;
214 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: 199 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
215 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 200 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -235,7 +220,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
235 // set all of the components to the same value 220 // set all of the components to the same value
236 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 221 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
237 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); 222 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
238 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
239 break; 223 break;
240 case Vehicle.ANGULAR_MOTOR_DIRECTION: 224 case Vehicle.ANGULAR_MOTOR_DIRECTION:
241 m_angularMotorDirection = new Vector3(pValue, pValue, pValue); 225 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
@@ -244,7 +228,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
244 break; 228 break;
245 case Vehicle.LINEAR_FRICTION_TIMESCALE: 229 case Vehicle.LINEAR_FRICTION_TIMESCALE:
246 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); 230 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
247 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
248 break; 231 break;
249 case Vehicle.LINEAR_MOTOR_DIRECTION: 232 case Vehicle.LINEAR_MOTOR_DIRECTION:
250 m_linearMotorDirection = new Vector3(pValue, pValue, pValue); 233 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
@@ -265,7 +248,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
265 { 248 {
266 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 249 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
267 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 250 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
268 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
269 break; 251 break;
270 case Vehicle.ANGULAR_MOTOR_DIRECTION: 252 case Vehicle.ANGULAR_MOTOR_DIRECTION:
271 // Limit requested angular speed to 2 rps= 4 pi rads/sec 253 // Limit requested angular speed to 2 rps= 4 pi rads/sec
@@ -278,7 +260,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
278 break; 260 break;
279 case Vehicle.LINEAR_FRICTION_TIMESCALE: 261 case Vehicle.LINEAR_FRICTION_TIMESCALE:
280 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 262 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
281 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
282 break; 263 break;
283 case Vehicle.LINEAR_MOTOR_DIRECTION: 264 case Vehicle.LINEAR_MOTOR_DIRECTION:
284 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 265 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -559,25 +540,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
559 break; 540 break;
560 } 541 }
561 542
562 // Update any physical parameters based on this type. 543 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f);
563 Refresh(); 544 // m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
564
565 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
566 m_linearMotorDecayTimescale, m_linearFrictionTimescale,
567 1f);
568 m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
569 545
570 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, 546 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f);
571 m_angularMotorDecayTimescale, m_angularFrictionTimescale, 547 // m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
572 1f);
573 m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
574 548
575 /* Not implemented 549 /* Not implemented
576 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, 550 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
577 BSMotor.Infinite, BSMotor.InfiniteVector, 551 BSMotor.Infinite, BSMotor.InfiniteVector,
578 m_verticalAttractionEfficiency); 552 m_verticalAttractionEfficiency);
579 // Z goes away and we keep X and Y 553 // Z goes away and we keep X and Y
580 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
581 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 554 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
582 */ 555 */
583 556
@@ -589,6 +562,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
589 { 562 {
590 RegisterForSceneEvents(); 563 RegisterForSceneEvents();
591 } 564 }
565
566 // Update any physical parameters based on this type.
567 Refresh();
592 } 568 }
593 #endregion // Vehicle parameter setting 569 #endregion // Vehicle parameter setting
594 570
@@ -596,6 +572,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
596 public override void Refresh() 572 public override void Refresh()
597 { 573 {
598 // If asking for a refresh, reset the physical parameters before the next simulation step. 574 // If asking for a refresh, reset the physical parameters before the next simulation step.
575 // Called whether active or not since the active state may be updated before the next step.
599 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate() 576 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate()
600 { 577 {
601 SetPhysicalParameters(); 578 SetPhysicalParameters();
@@ -612,8 +589,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
612 m_vehicleMass = ControllingPrim.TotalMass; 589 m_vehicleMass = ControllingPrim.TotalMass;
613 590
614 // Friction affects are handled by this vehicle code 591 // Friction affects are handled by this vehicle code
615 m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction); 592 // m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction);
616 m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution); 593 // m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution);
594 ControllingPrim.Linkset.SetPhysicalFriction(BSParam.VehicleFriction);
595 ControllingPrim.Linkset.SetPhysicalRestitution(BSParam.VehicleRestitution);
617 596
618 // Moderate angular movement introduced by Bullet. 597 // Moderate angular movement introduced by Bullet.
619 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. 598 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
@@ -623,17 +602,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
623 m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor); 602 m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor);
624 603
625 // Vehicles report collision events so we know when it's on the ground 604 // Vehicles report collision events so we know when it's on the ground
626 m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 605 // m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
606 ControllingPrim.Linkset.AddToPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS);
627 607
628 ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape, m_vehicleMass); 608 // Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
629 m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); 609 // ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor;
630 m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); 610 // m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
611 // m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);
612 ControllingPrim.Linkset.ComputeAndSetLocalInertia(BSParam.VehicleInertiaFactor, m_vehicleMass);
631 613
632 // Set the gravity for the vehicle depending on the buoyancy 614 // Set the gravity for the vehicle depending on the buoyancy
633 // TODO: what should be done if prim and vehicle buoyancy differ? 615 // TODO: what should be done if prim and vehicle buoyancy differ?
634 m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); 616 m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy);
635 // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same. 617 // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same.
636 m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero); 618 // m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero);
619 ControllingPrim.Linkset.SetPhysicalGravity(Vector3.Zero);
637 620
638 VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", 621 VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}",
639 ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity, 622 ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity,
@@ -645,11 +628,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
645 { 628 {
646 if (ControllingPrim.PhysBody.HasPhysicalBody) 629 if (ControllingPrim.PhysBody.HasPhysicalBody)
647 m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 630 m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
631 // ControllingPrim.Linkset.RemoveFromPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS);
648 } 632 }
649 } 633 }
650 634
651 // BSActor.RemoveBodyDependencies 635 // BSActor.RemoveBodyDependencies
652 public override void RemoveBodyDependencies() 636 public override void RemoveDependencies()
653 { 637 {
654 Refresh(); 638 Refresh();
655 } 639 }
@@ -657,6 +641,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
657 // BSActor.Release() 641 // BSActor.Release()
658 public override void Dispose() 642 public override void Dispose()
659 { 643 {
644 VDetailLog("{0},Dispose", ControllingPrim.LocalID);
660 UnregisterForSceneEvents(); 645 UnregisterForSceneEvents();
661 Type = Vehicle.TYPE_NONE; 646 Type = Vehicle.TYPE_NONE;
662 Enabled = false; 647 Enabled = false;
@@ -714,7 +699,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
714 private Vector3 m_knownRotationalVelocity; 699 private Vector3 m_knownRotationalVelocity;
715 private Vector3 m_knownRotationalForce; 700 private Vector3 m_knownRotationalForce;
716 private Vector3 m_knownRotationalImpulse; 701 private Vector3 m_knownRotationalImpulse;
717 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
718 702
719 private const int m_knownChangedPosition = 1 << 0; 703 private const int m_knownChangedPosition = 1 << 0;
720 private const int m_knownChangedVelocity = 1 << 1; 704 private const int m_knownChangedVelocity = 1 << 1;
@@ -726,7 +710,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
726 private const int m_knownChangedRotationalImpulse = 1 << 7; 710 private const int m_knownChangedRotationalImpulse = 1 << 7;
727 private const int m_knownChangedTerrainHeight = 1 << 8; 711 private const int m_knownChangedTerrainHeight = 1 << 8;
728 private const int m_knownChangedWaterLevel = 1 << 9; 712 private const int m_knownChangedWaterLevel = 1 << 9;
729 private const int m_knownChangedForwardVelocity = 1 <<10;
730 713
731 public void ForgetKnownVehicleProperties() 714 public void ForgetKnownVehicleProperties()
732 { 715 {
@@ -783,13 +766,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
783 766
784 // Since the computation of terrain height can be a little involved, this routine 767 // Since the computation of terrain height can be a little involved, this routine
785 // is used to fetch the height only once for each vehicle simulation step. 768 // is used to fetch the height only once for each vehicle simulation step.
786 Vector3 lastRememberedHeightPos; 769 Vector3 lastRememberedHeightPos = new Vector3(-1, -1, -1);
787 private float GetTerrainHeight(Vector3 pos) 770 private float GetTerrainHeight(Vector3 pos)
788 { 771 {
789 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) 772 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos)
790 { 773 {
791 lastRememberedHeightPos = pos; 774 lastRememberedHeightPos = pos;
792 m_knownTerrainHeight = ControllingPrim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 775 m_knownTerrainHeight = ControllingPrim.PhysScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
793 m_knownHas |= m_knownChangedTerrainHeight; 776 m_knownHas |= m_knownChangedTerrainHeight;
794 } 777 }
795 return m_knownTerrainHeight; 778 return m_knownTerrainHeight;
@@ -797,14 +780,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
797 780
798 // Since the computation of water level can be a little involved, this routine 781 // Since the computation of water level can be a little involved, this routine
799 // is used ot fetch the level only once for each vehicle simulation step. 782 // is used ot fetch the level only once for each vehicle simulation step.
783 Vector3 lastRememberedWaterHeightPos = new Vector3(-1, -1, -1);
800 private float GetWaterLevel(Vector3 pos) 784 private float GetWaterLevel(Vector3 pos)
801 { 785 {
802 if ((m_knownHas & m_knownChangedWaterLevel) == 0) 786 if ((m_knownHas & m_knownChangedWaterLevel) == 0 || pos != lastRememberedWaterHeightPos)
803 { 787 {
804 m_knownWaterLevel = ControllingPrim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); 788 lastRememberedWaterHeightPos = pos;
789 m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos);
805 m_knownHas |= m_knownChangedWaterLevel; 790 m_knownHas |= m_knownChangedWaterLevel;
806 } 791 }
807 return (float)m_knownWaterLevel; 792 return m_knownWaterLevel;
808 } 793 }
809 794
810 private Vector3 VehiclePosition 795 private Vector3 VehiclePosition
@@ -930,14 +915,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
930 { 915 {
931 get 916 get
932 { 917 {
933 if ((m_knownHas & m_knownChangedForwardVelocity) == 0) 918 return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
934 {
935 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
936 m_knownHas |= m_knownChangedForwardVelocity;
937 }
938 return m_knownForwardVelocity;
939 } 919 }
940 } 920 }
921
941 private float VehicleForwardSpeed 922 private float VehicleForwardSpeed
942 { 923 {
943 get 924 get
@@ -988,6 +969,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
988 { 969 {
989 ComputeLinearVelocity(pTimestep); 970 ComputeLinearVelocity(pTimestep);
990 971
972 ComputeLinearDeflection(pTimestep);
973
991 ComputeLinearTerrainHeightCorrection(pTimestep); 974 ComputeLinearTerrainHeightCorrection(pTimestep);
992 975
993 ComputeLinearHover(pTimestep); 976 ComputeLinearHover(pTimestep);
@@ -1003,11 +986,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1003 { 986 {
1004 Vector3 vel = VehicleVelocity; 987 Vector3 vel = VehicleVelocity;
1005 if ((m_flags & (VehicleFlag.NO_X)) != 0) 988 if ((m_flags & (VehicleFlag.NO_X)) != 0)
989 {
1006 vel.X = 0; 990 vel.X = 0;
991 }
1007 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 992 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
993 {
1008 vel.Y = 0; 994 vel.Y = 0;
995 }
1009 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 996 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
997 {
1010 vel.Z = 0; 998 vel.Z = 0;
999 }
1011 VehicleVelocity = vel; 1000 VehicleVelocity = vel;
1012 } 1001 }
1013 1002
@@ -1019,13 +1008,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1019 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG 1008 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG
1020 VehicleVelocity /= VehicleVelocity.Length(); 1009 VehicleVelocity /= VehicleVelocity.Length();
1021 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity; 1010 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity;
1022 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}", 1011 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}",
1023 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity); 1012 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity);
1024 } 1013 }
1025 else if (newVelocityLengthSq < 0.001f) 1014 else if (newVelocityLengthSq < 0.001f)
1026 VehicleVelocity = Vector3.Zero; 1015 VehicleVelocity = Vector3.Zero;
1027 1016
1028 VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.IsColliding, VehicleVelocity ); 1017 VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, VehicleVelocity );
1029 1018
1030 } // end MoveLinear() 1019 } // end MoveLinear()
1031 1020
@@ -1033,9 +1022,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1033 { 1022 {
1034 // Step the motor from the current value. Get the correction needed this step. 1023 // Step the motor from the current value. Get the correction needed this step.
1035 Vector3 origVelW = VehicleVelocity; // DEBUG 1024 Vector3 origVelW = VehicleVelocity; // DEBUG
1036 Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); 1025 Vector3 currentVelV = VehicleForwardVelocity;
1037 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); 1026 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
1038 1027
1028 // Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction.
1029 Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
1030 linearMotorCorrectionV -= (currentVelV * frictionFactorV);
1031
1039 // Motor is vehicle coordinates. Rotate it to world coordinates 1032 // Motor is vehicle coordinates. Rotate it to world coordinates
1040 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; 1033 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
1041 1034
@@ -1049,8 +1042,49 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1049 // Add this correction to the velocity to make it faster/slower. 1042 // Add this correction to the velocity to make it faster/slower.
1050 VehicleVelocity += linearMotorVelocityW; 1043 VehicleVelocity += linearMotorVelocityW;
1051 1044
1052 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5}", 1045 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},tgt={3},correctV={4},correctW={5},newVelW={6},fricFact={7}",
1053 ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, linearMotorVelocityW, VehicleVelocity); 1046 ControllingPrim.LocalID, origVelW, currentVelV, m_linearMotor.TargetValue, linearMotorCorrectionV,
1047 linearMotorVelocityW, VehicleVelocity, frictionFactorV);
1048 }
1049
1050 //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis
1051 //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity
1052 private void ComputeLinearDeflection(float pTimestep)
1053 {
1054 Vector3 linearDeflectionV = Vector3.Zero;
1055 Vector3 velocityV = VehicleForwardVelocity;
1056
1057 if (BSParam.VehicleEnableLinearDeflection)
1058 {
1059 // Velocity in Y and Z dimensions is movement to the side or turning.
1060 // Compute deflection factor from the to the side and rotational velocity
1061 linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y);
1062 linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z);
1063
1064 // Velocity to the side and around is corrected and moved into the forward direction
1065 linearDeflectionV.X += Math.Abs(linearDeflectionV.Y);
1066 linearDeflectionV.X += Math.Abs(linearDeflectionV.Z);
1067
1068 // Scale the deflection to the fractional simulation time
1069 linearDeflectionV *= pTimestep;
1070
1071 // Subtract the sideways and rotational velocity deflection factors while adding the correction forward
1072 linearDeflectionV *= new Vector3(1, -1, -1);
1073
1074 // Correction is vehicle relative. Convert to world coordinates.
1075 Vector3 linearDeflectionW = linearDeflectionV * VehicleOrientation;
1076
1077 // Optionally, if not colliding, don't effect world downward velocity. Let falling things fall.
1078 if (BSParam.VehicleLinearDeflectionNotCollidingNoZ && !m_controllingPrim.HasSomeCollision)
1079 {
1080 linearDeflectionW.Z = 0f;
1081 }
1082
1083 VehicleVelocity += linearDeflectionW;
1084
1085 VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}",
1086 ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV);
1087 }
1054 } 1088 }
1055 1089
1056 public void ComputeLinearTerrainHeightCorrection(float pTimestep) 1090 public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@@ -1087,14 +1121,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1087 { 1121 {
1088 m_VhoverTargetHeight = m_VhoverHeight; 1122 m_VhoverTargetHeight = m_VhoverHeight;
1089 } 1123 }
1090
1091 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) 1124 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
1092 { 1125 {
1093 // If body is already heigher, use its height as target height 1126 // If body is already heigher, use its height as target height
1094 if (VehiclePosition.Z > m_VhoverTargetHeight) 1127 if (VehiclePosition.Z > m_VhoverTargetHeight)
1128 {
1095 m_VhoverTargetHeight = VehiclePosition.Z; 1129 m_VhoverTargetHeight = VehiclePosition.Z;
1130
1131 // A 'misfeature' of this flag is that if the vehicle is above it's hover height,
1132 // the vehicle's buoyancy goes away. This is an SL bug that got used by so many
1133 // scripts that it could not be changed.
1134 // So, if above the height, reapply gravity if buoyancy had it turned off.
1135 if (m_VehicleBuoyancy != 0)
1136 {
1137 Vector3 appliedGravity = ControllingPrim.ComputeGravity(ControllingPrim.Buoyancy) * m_vehicleMass;
1138 VehicleAddForce(appliedGravity);
1139 }
1140 }
1096 } 1141 }
1097 1142
1098 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 1143 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
1099 { 1144 {
1100 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) 1145 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
@@ -1136,7 +1181,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1136 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, 1181 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
1137 verticalError, verticalCorrection); 1182 verticalError, verticalCorrection);
1138 } 1183 }
1139
1140 } 1184 }
1141 } 1185 }
1142 1186
@@ -1188,7 +1232,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1188 // used with conjunction with banking: the strength of the banking will decay when the 1232 // used with conjunction with banking: the strength of the banking will decay when the
1189 // vehicle no longer experiences collisions. The decay timescale is the same as 1233 // vehicle no longer experiences collisions. The decay timescale is the same as
1190 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering 1234 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
1191 // when they are in mid jump. 1235 // when they are in mid jump.
1192 // TODO: this code is wrong. Also, what should it do for boats (height from water)? 1236 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
1193 // This is just using the ground and a general collision check. Should really be using 1237 // This is just using the ground and a general collision check. Should really be using
1194 // a downward raycast to find what is below. 1238 // a downward raycast to find what is below.
@@ -1201,7 +1245,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1201 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); 1245 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
1202 distanceAboveGround = VehiclePosition.Z - targetHeight; 1246 distanceAboveGround = VehiclePosition.Z - targetHeight;
1203 // Not colliding if the vehicle is off the ground 1247 // Not colliding if the vehicle is off the ground
1204 if (!Prim.IsColliding) 1248 if (!Prim.HasSomeCollision)
1205 { 1249 {
1206 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1250 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
1207 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); 1251 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround);
@@ -1212,12 +1256,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1212 // be computed with a motor. 1256 // be computed with a motor.
1213 // TODO: add interaction with banking. 1257 // TODO: add interaction with banking.
1214 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", 1258 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
1215 Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); 1259 Prim.LocalID, distanceAboveGround, Prim.HasSomeCollision, ret);
1216 */ 1260 */
1217 1261
1218 // Another approach is to measure if we're going up. If going up and not colliding, 1262 // Another approach is to measure if we're going up. If going up and not colliding,
1219 // the vehicle is in the air. Fix that by pushing down. 1263 // the vehicle is in the air. Fix that by pushing down.
1220 if (!ControllingPrim.IsColliding && VehicleVelocity.Z > 0.1) 1264 if (!ControllingPrim.HasSomeCollision && VehicleVelocity.Z > 0.1)
1221 { 1265 {
1222 // Get rid of any of the velocity vector that is pushing us up. 1266 // Get rid of any of the velocity vector that is pushing us up.
1223 float upVelocity = VehicleVelocity.Z; 1267 float upVelocity = VehicleVelocity.Z;
@@ -1239,7 +1283,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1239 } 1283 }
1240 */ 1284 */
1241 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", 1285 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}",
1242 ControllingPrim.LocalID, ControllingPrim.IsColliding, upVelocity, VehicleVelocity); 1286 ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, upVelocity, VehicleVelocity);
1243 } 1287 }
1244 } 1288 }
1245 } 1289 }
@@ -1249,14 +1293,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1249 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; 1293 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass;
1250 1294
1251 // Hack to reduce downward force if the vehicle is probably sitting on the ground 1295 // Hack to reduce downward force if the vehicle is probably sitting on the ground
1252 if (ControllingPrim.IsColliding && IsGroundVehicle) 1296 if (ControllingPrim.HasSomeCollision && IsGroundVehicle)
1253 appliedGravity *= BSParam.VehicleGroundGravityFudge; 1297 appliedGravity *= BSParam.VehicleGroundGravityFudge;
1254 1298
1255 VehicleAddForce(appliedGravity); 1299 VehicleAddForce(appliedGravity);
1256 1300
1257 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}", 1301 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={5}",
1258 ControllingPrim.LocalID, m_VehicleGravity, 1302 ControllingPrim.LocalID, m_VehicleGravity,
1259 ControllingPrim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); 1303 ControllingPrim.HasSomeCollision, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity);
1260 } 1304 }
1261 1305
1262 // ======================================================================= 1306 // =======================================================================
@@ -1323,6 +1367,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1323 private void ComputeAngularTurning(float pTimestep) 1367 private void ComputeAngularTurning(float pTimestep)
1324 { 1368 {
1325 // The user wants this many radians per second angular change? 1369 // The user wants this many radians per second angular change?
1370 Vector3 origVehicleRotationalVelocity = VehicleRotationalVelocity; // DEBUG DEBUG
1326 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation); 1371 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation);
1327 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV); 1372 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV);
1328 1373
@@ -1330,18 +1375,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1330 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : 1375 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1331 // This flag prevents linear deflection parallel to world z-axis. This is useful 1376 // This flag prevents linear deflection parallel to world z-axis. This is useful
1332 // for preventing ground vehicles with large linear deflection, like bumper cars, 1377 // for preventing ground vehicles with large linear deflection, like bumper cars,
1333 // from climbing their linear deflection into the sky. 1378 // from climbing their linear deflection into the sky.
1334 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement 1379 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
1335 // TODO: This is here because this is where ODE put it but documentation says it 1380 // TODO: This is here because this is where ODE put it but documentation says it
1336 // is a linear effect. Where should this check go? 1381 // is a linear effect. Where should this check go?
1337 //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 1382 //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1338 // { 1383 // {
1339 // angularMotorContributionV.X = 0f; 1384 // angularMotorContributionV.X = 0f;
1340 // angularMotorContributionV.Y = 0f; 1385 // angularMotorContributionV.Y = 0f;
1341 // } 1386 // }
1387
1388 // Reduce any velocity by friction.
1389 Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep);
1390 angularMotorContributionV -= (currentAngularV * frictionFactorW);
1391
1392 Vector3 angularMotorContributionW = angularMotorContributionV * VehicleOrientation;
1393 VehicleRotationalVelocity += angularMotorContributionW;
1342 1394
1343 VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; 1395 VDetailLog("{0}, MoveAngular,angularTurning,curAngVelV={1},origVehRotVel={2},vehRotVel={3},frictFact={4}, angContribV={5},angContribW={6}",
1344 VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", ControllingPrim.LocalID, angularMotorContributionV); 1396 ControllingPrim.LocalID, currentAngularV, origVehicleRotationalVelocity, VehicleRotationalVelocity, frictionFactorW, angularMotorContributionV, angularMotorContributionW);
1345 } 1397 }
1346 1398
1347 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: 1399 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
@@ -1356,86 +1408,136 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1356 { 1408 {
1357 1409
1358 // If vertical attaction timescale is reasonable 1410 // If vertical attaction timescale is reasonable
1359 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1411 if (BSParam.VehicleEnableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1360 { 1412 {
1361 // Possible solution derived from a discussion at: 1413 Vector3 vehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
1362 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no 1414 switch (BSParam.VehicleAngularVerticalAttractionAlgorithm)
1363
1364 // Create a rotation that is only the vehicle's rotation around Z
1365 Vector3 currentEuler = Vector3.Zero;
1366 VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
1367 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
1368
1369 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1370 Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1371 // Compute the angle between those to vectors.
1372 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1373 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1374
1375 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1376 // TODO: add 'efficiency'.
1377 differenceAngle /= m_verticalAttractionTimescale;
1378
1379 // Create the quaterian representing the correction angle
1380 Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
1381
1382 // Turn that quaternion into Euler values to make it into velocities to apply.
1383 Vector3 vertContributionV = Vector3.Zero;
1384 correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
1385 vertContributionV *= -1f;
1386
1387 VehicleRotationalVelocity += vertContributionV;
1388
1389 VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}",
1390 ControllingPrim.LocalID,
1391 differenceAxis,
1392 differenceAngle,
1393 correctionRotation,
1394 vertContributionV);
1395
1396 // ===================================================================
1397 /*
1398 Vector3 vertContributionV = Vector3.Zero;
1399 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1400
1401 // Take a vector pointing up and convert it from world to vehicle relative coords.
1402 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1403
1404 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1405 // is now:
1406 // leaning to one side: rotated around the X axis with the Y value going
1407 // from zero (nearly straight up) to one (completely to the side)) or
1408 // leaning front-to-back: rotated around the Y axis with the value of X being between
1409 // zero and one.
1410 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1411
1412 // Y error means needed rotation around X axis and visa versa.
1413 // Since the error goes from zero to one, the asin is the corresponding angle.
1414 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1415 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1416 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1417
1418 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1419 if (verticalError.Z < 0f)
1420 { 1415 {
1421 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; 1416 case 0:
1422 // vertContribution.Y -= PIOverFour; 1417 {
1418 //Another formula to try got from :
1419 //http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html
1420
1421 // Flipping what was originally a timescale into a speed variable and then multiplying it by 2
1422 // since only computing half the distance between the angles.
1423 float verticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
1424
1425 // Make a prediction of where the up axis will be when this is applied rather then where it is now as
1426 // this makes for a smoother adjustment and less fighting between the various forces.
1427 Vector3 predictedUp = vehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1428
1429 // This is only half the distance to the target so it will take 2 seconds to complete the turn.
1430 Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
1431
1432 // Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
1433 Vector3 vertContributionV = torqueVector * verticalAttractionSpeed * verticalAttractionSpeed;
1434
1435 VehicleRotationalVelocity += vertContributionV;
1436
1437 VDetailLog("{0}, MoveAngular,verticalAttraction,vertAttrSpeed={1},upAxis={2},PredictedUp={3},torqueVector={4},contrib={5}",
1438 ControllingPrim.LocalID,
1439 verticalAttractionSpeed,
1440 vehicleUpAxis,
1441 predictedUp,
1442 torqueVector,
1443 vertContributionV);
1444 break;
1445 }
1446 case 1:
1447 {
1448 // Possible solution derived from a discussion at:
1449 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
1450
1451 // Create a rotation that is only the vehicle's rotation around Z
1452 Vector3 currentEulerW = Vector3.Zero;
1453 VehicleOrientation.GetEulerAngles(out currentEulerW.X, out currentEulerW.Y, out currentEulerW.Z);
1454 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEulerW.Z);
1455
1456 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1457 Vector3 differenceAxisW = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1458 // Compute the angle between those to vectors.
1459 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1460 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1461
1462 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1463 // TODO: add 'efficiency'.
1464 // differenceAngle /= m_verticalAttractionTimescale;
1465
1466 // Create the quaterian representing the correction angle
1467 Quaternion correctionRotationW = Quaternion.CreateFromAxisAngle(differenceAxisW, (float)differenceAngle);
1468
1469 // Turn that quaternion into Euler values to make it into velocities to apply.
1470 Vector3 vertContributionW = Vector3.Zero;
1471 correctionRotationW.GetEulerAngles(out vertContributionW.X, out vertContributionW.Y, out vertContributionW.Z);
1472 vertContributionW *= -1f;
1473 vertContributionW /= m_verticalAttractionTimescale;
1474
1475 VehicleRotationalVelocity += vertContributionW;
1476
1477 VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},diffAxis={2},diffAng={3},corrRot={4},contrib={5}",
1478 ControllingPrim.LocalID,
1479 vehicleUpAxis,
1480 differenceAxisW,
1481 differenceAngle,
1482 correctionRotationW,
1483 vertContributionW);
1484 break;
1485 }
1486 case 2:
1487 {
1488 Vector3 vertContributionV = Vector3.Zero;
1489 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1490
1491 // Take a vector pointing up and convert it from world to vehicle relative coords.
1492 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1493
1494 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1495 // is now:
1496 // leaning to one side: rotated around the X axis with the Y value going
1497 // from zero (nearly straight up) to one (completely to the side)) or
1498 // leaning front-to-back: rotated around the Y axis with the value of X being between
1499 // zero and one.
1500 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1501
1502 // Y error means needed rotation around X axis and visa versa.
1503 // Since the error goes from zero to one, the asin is the corresponding angle.
1504 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1505 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1506 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1507
1508 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1509 if (verticalError.Z < 0f)
1510 {
1511 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour;
1512 // vertContribution.Y -= PIOverFour;
1513 }
1514
1515 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1516 // Correction happens over a number of seconds.
1517 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1518
1519 // The correction happens over the user's time period
1520 vertContributionV /= m_verticalAttractionTimescale;
1521
1522 // Rotate the vehicle rotation to the world coordinates.
1523 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1524
1525 VDetailLog("{0}, MoveAngular,verticalAttraction,,upAxis={1},origRotVW={2},vertError={3},unscaledV={4},eff={5},ts={6},vertContribV={7}",
1526 ControllingPrim.LocalID,
1527 vehicleUpAxis,
1528 origRotVelW,
1529 verticalError,
1530 unscaledContribVerticalErrorV,
1531 m_verticalAttractionEfficiency,
1532 m_verticalAttractionTimescale,
1533 vertContributionV);
1534 break;
1535 }
1536 default:
1537 {
1538 break;
1539 }
1423 } 1540 }
1424
1425 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1426 // Correction happens over a number of seconds.
1427 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1428
1429 // The correction happens over the user's time period
1430 vertContributionV /= m_verticalAttractionTimescale;
1431
1432 // Rotate the vehicle rotation to the world coordinates.
1433 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1434
1435 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
1436 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
1437 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
1438 */
1439 } 1541 }
1440 } 1542 }
1441 1543
@@ -1445,13 +1547,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1445 // in that direction. 1547 // in that direction.
1446 // TODO: implement reference frame. 1548 // TODO: implement reference frame.
1447 public void ComputeAngularDeflection() 1549 public void ComputeAngularDeflection()
1448 { 1550 {
1449 // Since angularMotorUp and angularDeflection are computed independently, they will calculate
1450 // approximately the same X or Y correction. When added together (when contributions are combined)
1451 // this creates an over-correction and then wabbling as the target is overshot.
1452 // TODO: rethink how the different correction computations inter-relate.
1453 1551
1454 if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) 1552 if (BSParam.VehicleEnableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
1455 { 1553 {
1456 Vector3 deflectContributionV = Vector3.Zero; 1554 Vector3 deflectContributionV = Vector3.Zero;
1457 1555
@@ -1464,10 +1562,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1464 1562
1465 // The direction the vehicle is pointing 1563 // The direction the vehicle is pointing
1466 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; 1564 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1467 pointingDirection.Normalize(); 1565 //Predict where the Vehicle will be pointing after AngularVelocity change is applied. This will keep
1566 // from overshooting and allow this correction to merge with the Vertical Attraction peacefully.
1567 Vector3 predictedPointingDirection = pointingDirection * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1568 predictedPointingDirection.Normalize();
1468 1569
1469 // The difference between what is and what should be. 1570 // The difference between what is and what should be.
1470 Vector3 deflectionError = movingDirection - pointingDirection; 1571 // Vector3 deflectionError = movingDirection - predictedPointingDirection;
1572 Vector3 deflectionError = Vector3.Cross(movingDirection, predictedPointingDirection);
1471 1573
1472 // Don't try to correct very large errors (not our job) 1574 // Don't try to correct very large errors (not our job)
1473 // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X); 1575 // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X);
@@ -1480,15 +1582,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1480 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); 1582 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1481 1583
1482 // Scale the correction by recovery timescale and efficiency 1584 // Scale the correction by recovery timescale and efficiency
1483 deflectContributionV = (-deflectionError) * m_angularDeflectionEfficiency; 1585 // Not modeling a spring so clamp the scale to no more then the arc
1484 deflectContributionV /= m_angularDeflectionTimescale; 1586 deflectContributionV = (-deflectionError) * ClampInRange(0, m_angularDeflectionEfficiency/m_angularDeflectionTimescale,1f);
1485 1587 //deflectContributionV /= m_angularDeflectionTimescale;
1486 VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1487 1588
1589 // VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1590 VehicleRotationalVelocity += deflectContributionV;
1488 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", 1591 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1489 ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); 1592 ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV);
1490 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", 1593 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3},PredictedPointingDir={4}",
1491 ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); 1594 ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale, predictedPointingDirection);
1492 } 1595 }
1493 } 1596 }
1494 1597
@@ -1500,13 +1603,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1500 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude 1603 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
1501 // of the yaw effect will be proportional to the 1604 // of the yaw effect will be proportional to the
1502 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's 1605 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1503 // velocity along its preferred axis of motion. 1606 // velocity along its preferred axis of motion.
1504 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any 1607 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
1505 // positive rotation (by the right-hand rule) about the roll-axis will effect a 1608 // positive rotation (by the right-hand rule) about the roll-axis will effect a
1506 // (negative) torque around the yaw-axis, making it turn to the right--that is the 1609 // (negative) torque around the yaw-axis, making it turn to the right--that is the
1507 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. 1610 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
1508 // Negating the banking coefficient will make it so that the vehicle leans to the 1611 // Negating the banking coefficient will make it so that the vehicle leans to the
1509 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). 1612 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
1510 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making 1613 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
1511 // banking vehicles do what you want rather than what the laws of physics allow. 1614 // banking vehicles do what you want rather than what the laws of physics allow.
1512 // For example, consider a real motorcycle...it must be moving forward in order for 1615 // For example, consider a real motorcycle...it must be moving forward in order for
@@ -1518,14 +1621,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1518 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the 1621 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
1519 // banking effect depends only on the vehicle's rotation about its roll-axis compared 1622 // banking effect depends only on the vehicle's rotation about its roll-axis compared
1520 // to "dynamic" where the banking is also proportional to its velocity along its 1623 // to "dynamic" where the banking is also proportional to its velocity along its
1521 // roll-axis. Finding the best value of the "mixture" will probably require trial and error. 1624 // roll-axis. Finding the best value of the "mixture" will probably require trial and error.
1522 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the 1625 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the
1523 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to 1626 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1524 // bank quickly then give it a banking timescale of about a second or less, otherwise you can 1627 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1525 // make a sluggish vehicle by giving it a timescale of several seconds. 1628 // make a sluggish vehicle by giving it a timescale of several seconds.
1526 public void ComputeAngularBanking() 1629 public void ComputeAngularBanking()
1527 { 1630 {
1528 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1631 if (BSParam.VehicleEnableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1529 { 1632 {
1530 Vector3 bankingContributionV = Vector3.Zero; 1633 Vector3 bankingContributionV = Vector3.Zero;
1531 1634
@@ -1551,7 +1654,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1551 1654
1552 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; 1655 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation;
1553 VehicleRotationalVelocity += bankingContributionV; 1656 VehicleRotationalVelocity += bankingContributionV;
1554 1657
1555 1658
1556 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", 1659 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}",
1557 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); 1660 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV);
@@ -1598,6 +1701,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1598 1701
1599 } 1702 }
1600 1703
1704 // Given a friction vector (reduction in seconds) and a timestep, return the factor to reduce
1705 // some value by to apply this friction.
1706 private Vector3 ComputeFrictionFactor(Vector3 friction, float pTimestep)
1707 {
1708 Vector3 frictionFactor = Vector3.Zero;
1709 if (friction != BSMotor.InfiniteVector)
1710 {
1711 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
1712 // Individual friction components can be 'infinite' so compute each separately.
1713 frictionFactor.X = (friction.X == BSMotor.Infinite) ? 0f : (1f / friction.X);
1714 frictionFactor.Y = (friction.Y == BSMotor.Infinite) ? 0f : (1f / friction.Y);
1715 frictionFactor.Z = (friction.Z == BSMotor.Infinite) ? 0f : (1f / friction.Z);
1716 frictionFactor *= pTimestep;
1717 }
1718 return frictionFactor;
1719 }
1720
1721 private float SortedClampInRange(float clampa, float val, float clampb)
1722 {
1723 if (clampa > clampb)
1724 {
1725 float temp = clampa;
1726 clampa = clampb;
1727 clampb = temp;
1728 }
1729 return ClampInRange(clampa, val, clampb);
1730
1731 }
1732
1601 private float ClampInRange(float low, float val, float high) 1733 private float ClampInRange(float low, float val, float high)
1602 { 1734 {
1603 return Math.Max(low, Math.Min(val, high)); 1735 return Math.Max(low, Math.Min(val, high));
@@ -1607,8 +1739,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1607 // Invoke the detailed logger and output something if it's enabled. 1739 // Invoke the detailed logger and output something if it's enabled.
1608 private void VDetailLog(string msg, params Object[] args) 1740 private void VDetailLog(string msg, params Object[] args)
1609 { 1741 {
1610 if (ControllingPrim.PhysicsScene.VehicleLoggingEnabled) 1742 if (ControllingPrim.PhysScene.VehicleLoggingEnabled)
1611 ControllingPrim.PhysicsScene.DetailLog(msg, args); 1743 ControllingPrim.PhysScene.DetailLog(msg, args);
1612 } 1744 }
1613 } 1745 }
1614} 1746}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 4ece1eb..77f69a5 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -33,14 +33,6 @@ using OMV = OpenMetaverse;
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 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
44public abstract class BSLinkset 36public abstract class BSLinkset
45{ 37{
46 // private static string LogHeader = "[BULLETSIM LINKSET]"; 38 // private static string LogHeader = "[BULLETSIM LINKSET]";
@@ -56,15 +48,15 @@ public abstract class BSLinkset
56 { 48 {
57 BSLinkset ret = null; 49 BSLinkset ret = null;
58 50
59 switch ((int)BSParam.LinksetImplementation) 51 switch (parent.LinksetType)
60 { 52 {
61 case (int)LinksetImplementation.Constraint: 53 case LinksetImplementation.Constraint:
62 ret = new BSLinksetConstraints(physScene, parent); 54 ret = new BSLinksetConstraints(physScene, parent);
63 break; 55 break;
64 case (int)LinksetImplementation.Compound: 56 case LinksetImplementation.Compound:
65 ret = new BSLinksetCompound(physScene, parent); 57 ret = new BSLinksetCompound(physScene, parent);
66 break; 58 break;
67 case (int)LinksetImplementation.Manual: 59 case LinksetImplementation.Manual:
68 // ret = new BSLinksetManual(physScene, parent); 60 // ret = new BSLinksetManual(physScene, parent);
69 break; 61 break;
70 default: 62 default:
@@ -78,28 +70,37 @@ public abstract class BSLinkset
78 return ret; 70 return ret;
79 } 71 }
80 72
73 public class BSLinkInfo
74 {
75 public BSPrimLinkable member;
76 public BSLinkInfo(BSPrimLinkable pMember)
77 {
78 member = pMember;
79 }
80 public virtual void ResetLink() { }
81 public virtual void SetLinkParameters(BSConstraint constrain) { }
82 // Returns 'true' if physical property updates from the child should be reported to the simulator
83 public virtual bool ShouldUpdateChildProperties() { return false; }
84 }
85
86 public LinksetImplementation LinksetImpl { get; protected set; }
87
81 public BSPrimLinkable LinksetRoot { get; protected set; } 88 public BSPrimLinkable LinksetRoot { get; protected set; }
82 89
83 public BSScene PhysicsScene { get; private set; } 90 protected BSScene m_physicsScene { get; private set; }
84 91
85 static int m_nextLinksetID = 1; 92 static int m_nextLinksetID = 1;
86 public int LinksetID { get; private set; } 93 public int LinksetID { get; private set; }
87 94
88 // The children under the root in this linkset. 95 // The children under the root in this linkset.
89 protected HashSet<BSPrimLinkable> m_children; 96 // protected HashSet<BSPrimLinkable> m_children;
97 protected Dictionary<BSPrimLinkable, BSLinkInfo> m_children;
90 98
91 // We lock the diddling of linkset classes to prevent any badness. 99 // We lock the diddling of linkset classes to prevent any badness.
92 // This locks the modification of the instances of this class. Changes 100 // This locks the modification of the instances of this class. Changes
93 // to the physical representation is done via the tainting mechenism. 101 // to the physical representation is done via the tainting mechenism.
94 protected object m_linksetActivityLock = new Object(); 102 protected object m_linksetActivityLock = new Object();
95 103
96 // Some linksets have a preferred physical shape.
97 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
98 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
99 {
100 return BSPhysicsShapeType.SHAPE_UNKNOWN;
101 }
102
103 // We keep the prim's mass in the linkset structure since it could be dependent on other prims 104 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
104 public float LinksetMass { get; protected set; } 105 public float LinksetMass { get; protected set; }
105 106
@@ -122,9 +123,9 @@ public abstract class BSLinkset
122 // We create LOTS of linksets. 123 // We create LOTS of linksets.
123 if (m_nextLinksetID <= 0) 124 if (m_nextLinksetID <= 0)
124 m_nextLinksetID = 1; 125 m_nextLinksetID = 1;
125 PhysicsScene = scene; 126 m_physicsScene = scene;
126 LinksetRoot = parent; 127 LinksetRoot = parent;
127 m_children = new HashSet<BSPrimLinkable>(); 128 m_children = new Dictionary<BSPrimLinkable, BSLinkInfo>();
128 LinksetMass = parent.RawMass; 129 LinksetMass = parent.RawMass;
129 Rebuilding = false; 130 Rebuilding = false;
130 131
@@ -151,7 +152,7 @@ public abstract class BSLinkset
151 // Returns a new linkset for the child which is a linkset of one (just the 152 // Returns a new linkset for the child which is a linkset of one (just the
152 // orphened child). 153 // orphened child).
153 // Called at runtime. 154 // Called at runtime.
154 public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child) 155 public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child, bool inTaintTime)
155 { 156 {
156 lock (m_linksetActivityLock) 157 lock (m_linksetActivityLock)
157 { 158 {
@@ -160,12 +161,12 @@ public abstract class BSLinkset
160 // Cannot remove the root from a linkset. 161 // Cannot remove the root from a linkset.
161 return this; 162 return this;
162 } 163 }
163 RemoveChildFromLinkset(child); 164 RemoveChildFromLinkset(child, inTaintTime);
164 LinksetMass = ComputeLinksetMass(); 165 LinksetMass = ComputeLinksetMass();
165 } 166 }
166 167
167 // The child is down to a linkset of just itself 168 // The child is down to a linkset of just itself
168 return BSLinkset.Factory(PhysicsScene, child); 169 return BSLinkset.Factory(m_physicsScene, child);
169 } 170 }
170 171
171 // Return 'true' if the passed object is the root object of this linkset 172 // Return 'true' if the passed object is the root object of this linkset
@@ -185,17 +186,7 @@ public abstract class BSLinkset
185 bool ret = false; 186 bool ret = false;
186 lock (m_linksetActivityLock) 187 lock (m_linksetActivityLock)
187 { 188 {
188 ret = m_children.Contains(child); 189 ret = m_children.ContainsKey(child);
189 /* Safer version but the above should work
190 foreach (BSPrimLinkable bp in m_children)
191 {
192 if (child.LocalID == bp.LocalID)
193 {
194 ret = true;
195 break;
196 }
197 }
198 */
199 } 190 }
200 return ret; 191 return ret;
201 } 192 }
@@ -209,7 +200,35 @@ public abstract class BSLinkset
209 lock (m_linksetActivityLock) 200 lock (m_linksetActivityLock)
210 { 201 {
211 action(LinksetRoot); 202 action(LinksetRoot);
212 foreach (BSPrimLinkable po in m_children) 203 foreach (BSPrimLinkable po in m_children.Keys)
204 {
205 if (action(po))
206 break;
207 }
208 }
209 return ret;
210 }
211
212 public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
213 {
214 bool ret = false;
215 BSLinkInfo found = null;
216 lock (m_linksetActivityLock)
217 {
218 ret = m_children.TryGetValue(child, out found);
219 }
220 foundInfo = found;
221 return ret;
222 }
223 // Perform an action on each member of the linkset including root prim.
224 // Depends on the action on whether this should be done at taint time.
225 public delegate bool ForEachLinkInfoAction(BSLinkInfo obj);
226 public virtual bool ForEachLinkInfo(ForEachLinkInfoAction action)
227 {
228 bool ret = false;
229 lock (m_linksetActivityLock)
230 {
231 foreach (BSLinkInfo po in m_children.Values)
213 { 232 {
214 if (action(po)) 233 if (action(po))
215 break; 234 break;
@@ -218,13 +237,55 @@ public abstract class BSLinkset
218 return ret; 237 return ret;
219 } 238 }
220 239
240 // Check the type of the link and return 'true' if the link is flexible and the
241 // updates from the child should be sent to the simulator so things change.
242 public virtual bool ShouldReportPropertyUpdates(BSPrimLinkable child)
243 {
244 bool ret = false;
245
246 BSLinkInfo linkInfo;
247 if (m_children.TryGetValue(child, out linkInfo))
248 {
249 ret = linkInfo.ShouldUpdateChildProperties();
250 }
251
252 return ret;
253 }
254
255 // Called after a simulation step to post a collision with this object.
256 // Return 'true' if linkset processed the collision. 'false' says the linkset didn't have
257 // anything to add for the collision and it should be passed through normal processing.
258 // Default processing for a linkset.
259 public virtual bool HandleCollide(uint collidingWith, BSPhysObject collidee,
260 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
261 {
262 bool ret = false;
263
264 // prims in the same linkset cannot collide with each other
265 BSPrimLinkable convCollidee = collidee as BSPrimLinkable;
266 if (convCollidee != null && (LinksetID == convCollidee.Linkset.LinksetID))
267 {
268 // By returning 'true', we tell the caller the collision has been 'handled' so it won't
269 // do anything about this collision and thus, effectivily, ignoring the collision.
270 ret = true;
271 }
272 else
273 {
274 // Not a collision between members of the linkset. Must be a real collision.
275 // So the linkset root can know if there is a collision anywhere in the linkset.
276 LinksetRoot.SomeCollisionSimulationStep = m_physicsScene.SimulationStep;
277 }
278
279 return ret;
280 }
281
221 // I am the root of a linkset and a new child is being added 282 // I am the root of a linkset and a new child is being added
222 // Called while LinkActivity is locked. 283 // Called while LinkActivity is locked.
223 protected abstract void AddChildToLinkset(BSPrimLinkable child); 284 protected abstract void AddChildToLinkset(BSPrimLinkable child);
224 285
225 // I am the root of a linkset and one of my children is being removed. 286 // I am the root of a linkset and one of my children is being removed.
226 // Safe to call even if the child is not really in my linkset. 287 // Safe to call even if the child is not really in my linkset.
227 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child); 288 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime);
228 289
229 // When physical properties are changed the linkset needs to recalculate 290 // When physical properties are changed the linkset needs to recalculate
230 // its internal properties. 291 // its internal properties.
@@ -263,9 +324,88 @@ public abstract class BSLinkset
263 // This is called when the root body is changing. 324 // This is called when the root body is changing.
264 // Returns 'true' of something was actually removed and would need restoring 325 // Returns 'true' of something was actually removed and would need restoring
265 // Called at taint-time!! 326 // Called at taint-time!!
266 public abstract bool RemoveBodyDependencies(BSPrimLinkable child); 327 public abstract bool RemoveDependencies(BSPrimLinkable child);
267 328
268 // ================================================================ 329 // ================================================================
330 // Some physical setting happen to all members of the linkset
331 public virtual void SetPhysicalFriction(float friction)
332 {
333 ForEachMember((member) =>
334 {
335 if (member.PhysBody.HasPhysicalBody)
336 m_physicsScene.PE.SetFriction(member.PhysBody, friction);
337 return false; // 'false' says to continue looping
338 }
339 );
340 }
341 public virtual void SetPhysicalRestitution(float restitution)
342 {
343 ForEachMember((member) =>
344 {
345 if (member.PhysBody.HasPhysicalBody)
346 m_physicsScene.PE.SetRestitution(member.PhysBody, restitution);
347 return false; // 'false' says to continue looping
348 }
349 );
350 }
351 public virtual void SetPhysicalGravity(OMV.Vector3 gravity)
352 {
353 ForEachMember((member) =>
354 {
355 if (member.PhysBody.HasPhysicalBody)
356 m_physicsScene.PE.SetGravity(member.PhysBody, gravity);
357 return false; // 'false' says to continue looping
358 }
359 );
360 }
361 public virtual void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass)
362 {
363 ForEachMember((member) =>
364 {
365 if (member.PhysBody.HasPhysicalBody)
366 {
367 OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(member.PhysShape.physShapeInfo, linksetMass);
368 member.Inertia = inertia * inertiaFactor;
369 m_physicsScene.PE.SetMassProps(member.PhysBody, linksetMass, member.Inertia);
370 m_physicsScene.PE.UpdateInertiaTensor(member.PhysBody);
371 DetailLog("{0},BSLinkset.ComputeAndSetLocalInertia,m.mass={1}, inertia={2}", member.LocalID, linksetMass, member.Inertia);
372
373 }
374 return false; // 'false' says to continue looping
375 }
376 );
377 }
378 public virtual void SetPhysicalCollisionFlags(CollisionFlags collFlags)
379 {
380 ForEachMember((member) =>
381 {
382 if (member.PhysBody.HasPhysicalBody)
383 m_physicsScene.PE.SetCollisionFlags(member.PhysBody, collFlags);
384 return false; // 'false' says to continue looping
385 }
386 );
387 }
388 public virtual void AddToPhysicalCollisionFlags(CollisionFlags collFlags)
389 {
390 ForEachMember((member) =>
391 {
392 if (member.PhysBody.HasPhysicalBody)
393 m_physicsScene.PE.AddToCollisionFlags(member.PhysBody, collFlags);
394 return false; // 'false' says to continue looping
395 }
396 );
397 }
398 public virtual void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
399 {
400 ForEachMember((member) =>
401 {
402 if (member.PhysBody.HasPhysicalBody)
403 m_physicsScene.PE.RemoveFromCollisionFlags(member.PhysBody, collFlags);
404 return false; // 'false' says to continue looping
405 }
406 );
407 }
408 // ================================================================
269 protected virtual float ComputeLinksetMass() 409 protected virtual float ComputeLinksetMass()
270 { 410 {
271 float mass = LinksetRoot.RawMass; 411 float mass = LinksetRoot.RawMass;
@@ -273,7 +413,7 @@ public abstract class BSLinkset
273 { 413 {
274 lock (m_linksetActivityLock) 414 lock (m_linksetActivityLock)
275 { 415 {
276 foreach (BSPrimLinkable bp in m_children) 416 foreach (BSPrimLinkable bp in m_children.Keys)
277 { 417 {
278 mass += bp.RawMass; 418 mass += bp.RawMass;
279 } 419 }
@@ -291,7 +431,7 @@ public abstract class BSLinkset
291 com = LinksetRoot.Position * LinksetRoot.RawMass; 431 com = LinksetRoot.Position * LinksetRoot.RawMass;
292 float totalMass = LinksetRoot.RawMass; 432 float totalMass = LinksetRoot.RawMass;
293 433
294 foreach (BSPrimLinkable bp in m_children) 434 foreach (BSPrimLinkable bp in m_children.Keys)
295 { 435 {
296 com += bp.Position * bp.RawMass; 436 com += bp.Position * bp.RawMass;
297 totalMass += bp.RawMass; 437 totalMass += bp.RawMass;
@@ -310,7 +450,7 @@ public abstract class BSLinkset
310 { 450 {
311 com = LinksetRoot.Position; 451 com = LinksetRoot.Position;
312 452
313 foreach (BSPrimLinkable bp in m_children) 453 foreach (BSPrimLinkable bp in m_children.Keys)
314 { 454 {
315 com += bp.Position; 455 com += bp.Position;
316 } 456 }
@@ -320,12 +460,18 @@ public abstract class BSLinkset
320 return com; 460 return com;
321 } 461 }
322 462
463 #region Extension
464 public virtual object Extension(string pFunct, params object[] pParams)
465 {
466 return null;
467 }
468 #endregion // Extension
469
323 // Invoke the detailed logger and output something if it's enabled. 470 // Invoke the detailed logger and output something if it's enabled.
324 protected void DetailLog(string msg, params Object[] args) 471 protected void DetailLog(string msg, params Object[] args)
325 { 472 {
326 if (PhysicsScene.PhysicsLogging.Enabled) 473 if (m_physicsScene.PhysicsLogging.Enabled)
327 PhysicsScene.DetailLog(msg, args); 474 m_physicsScene.DetailLog(msg, args);
328 } 475 }
329
330} 476}
331} 477}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index e05562a..8f12189 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -35,103 +35,78 @@ using OMV = OpenMetaverse;
35namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37 37
38// When a child is linked, the relationship position of the child to the parent 38public sealed class BSLinksetCompound : BSLinkset
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{ 39{
43 public int Index; 40 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
44 public OMV.Vector3 OffsetFromRoot; 41
45 public OMV.Vector3 OffsetFromCenterOfMass; 42 public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
46 public OMV.Quaternion OffsetRot; 43 : base(scene, parent)
47 public BSLinksetCompoundInfo(int indx, OMV.Vector3 p, OMV.Quaternion r)
48 { 44 {
49 Index = indx; 45 LinksetImpl = LinksetImplementation.Compound;
50 OffsetFromRoot = p;
51 OffsetFromCenterOfMass = p;
52 OffsetRot = r;
53 } 46 }
54 // 'centerDisplacement' is the distance from the root the the center-of-mass (Bullet 'zero' of the shape) 47
55 public BSLinksetCompoundInfo(int indx, BSPrimLinkable root, BSPrimLinkable child, OMV.Vector3 centerDisplacement) 48 // ================================================================
49 // Changing the physical property of the linkset only needs to change the root
50 public override void SetPhysicalFriction(float friction)
56 { 51 {
57 // Each child position and rotation is given relative to the center-of-mass. 52 if (LinksetRoot.PhysBody.HasPhysicalBody)
58 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(root.RawOrientation); 53 m_physicsScene.PE.SetFriction(LinksetRoot.PhysBody, friction);
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 } 54 }
69 public override void Clear() 55 public override void SetPhysicalRestitution(float restitution)
70 { 56 {
71 Index = 0; 57 if (LinksetRoot.PhysBody.HasPhysicalBody)
72 OffsetFromRoot = OMV.Vector3.Zero; 58 m_physicsScene.PE.SetRestitution(LinksetRoot.PhysBody, restitution);
73 OffsetFromCenterOfMass = OMV.Vector3.Zero;
74 OffsetRot = OMV.Quaternion.Identity;
75 } 59 }
76 public override string ToString() 60 public override void SetPhysicalGravity(OMV.Vector3 gravity)
77 { 61 {
78 StringBuilder buff = new StringBuilder(); 62 if (LinksetRoot.PhysBody.HasPhysicalBody)
79 buff.Append("<i="); 63 m_physicsScene.PE.SetGravity(LinksetRoot.PhysBody, gravity);
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 } 64 }
90}; 65 public override void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass)
91
92public sealed class BSLinksetCompound : BSLinkset
93{
94 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
95
96 public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
97 : base(scene, parent)
98 { 66 {
67 OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(LinksetRoot.PhysShape.physShapeInfo, linksetMass);
68 LinksetRoot.Inertia = inertia * inertiaFactor;
69 m_physicsScene.PE.SetMassProps(LinksetRoot.PhysBody, linksetMass, LinksetRoot.Inertia);
70 m_physicsScene.PE.UpdateInertiaTensor(LinksetRoot.PhysBody);
99 } 71 }
100 72 public override void SetPhysicalCollisionFlags(CollisionFlags collFlags)
101 // For compound implimented linksets, if there are children, use compound shape for the root. 73 {
102 public override BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor) 74 if (LinksetRoot.PhysBody.HasPhysicalBody)
103 { 75 m_physicsScene.PE.SetCollisionFlags(LinksetRoot.PhysBody, collFlags);
104 // Returning 'unknown' means we don't have a preference. 76 }
105 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 77 public override void AddToPhysicalCollisionFlags(CollisionFlags collFlags)
106 if (IsRoot(requestor) && HasAnyChildren) 78 {
107 { 79 if (LinksetRoot.PhysBody.HasPhysicalBody)
108 ret = BSPhysicsShapeType.SHAPE_COMPOUND; 80 m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, collFlags);
109 }
110 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
111 return ret;
112 } 81 }
82 public override void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
83 {
84 if (LinksetRoot.PhysBody.HasPhysicalBody)
85 m_physicsScene.PE.RemoveFromCollisionFlags(LinksetRoot.PhysBody, collFlags);
86 }
87 // ================================================================
113 88
114 // When physical properties are changed the linkset needs to recalculate 89 // When physical properties are changed the linkset needs to recalculate
115 // its internal properties. 90 // its internal properties.
116 public override void Refresh(BSPrimLinkable requestor) 91 public override void Refresh(BSPrimLinkable requestor)
117 { 92 {
118 base.Refresh(requestor);
119
120 // Something changed so do the rebuilding thing 93 // Something changed so do the rebuilding thing
121 // ScheduleRebuild(); 94 ScheduleRebuild(requestor);
95 base.Refresh(requestor);
122 } 96 }
123 97
124 // Schedule a refresh to happen after all the other taint processing. 98 // Schedule a refresh to happen after all the other taint processing.
125 private void ScheduleRebuild(BSPrimLinkable requestor) 99 private void ScheduleRebuild(BSPrimLinkable requestor)
126 { 100 {
127 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}", 101 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}",
128 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren)); 102 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren));
103
129 // When rebuilding, it is possible to set properties that would normally require a rebuild. 104 // When rebuilding, it is possible to set properties that would normally require a rebuild.
130 // If already rebuilding, don't request another rebuild. 105 // If already rebuilding, don't request another rebuild.
131 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding. 106 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
132 if (!Rebuilding && HasAnyChildren) 107 if (!Rebuilding && HasAnyChildren)
133 { 108 {
134 PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate() 109 m_physicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
135 { 110 {
136 if (HasAnyChildren) 111 if (HasAnyChildren)
137 RecomputeLinksetCompound(); 112 RecomputeLinksetCompound();
@@ -151,47 +126,24 @@ public sealed class BSLinksetCompound : BSLinkset
151 if (IsRoot(child)) 126 if (IsRoot(child))
152 { 127 {
153 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly. 128 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
154 ScheduleRebuild(LinksetRoot); 129 Refresh(LinksetRoot);
155 }
156 else
157 {
158 // The origional prims are removed from the world as the shape of the root compound
159 // shape takes over.
160 PhysicsScene.PE.AddToCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
161 PhysicsScene.PE.ForceActivationState(child.PhysBody, ActivationState.DISABLE_SIMULATION);
162 // We don't want collisions from the old linkset children.
163 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
164
165 child.PhysBody.collisionType = CollisionType.LinksetChild;
166
167 ret = true;
168 } 130 }
169 return ret; 131 return ret;
170 } 132 }
171 133
172 // The object is going static (non-physical). Do any setup necessary for a static linkset. 134 // The object is going static (non-physical). We do not do anything for static linksets.
173 // Return 'true' if any properties updated on the passed object. 135 // Return 'true' if any properties updated on the passed object.
174 // This doesn't normally happen -- OpenSim removes the objects from the physical
175 // world if it is a static linkset.
176 // Called at taint-time! 136 // Called at taint-time!
177 public override bool MakeStatic(BSPrimLinkable child) 137 public override bool MakeStatic(BSPrimLinkable child)
178 { 138 {
179 bool ret = false; 139 bool ret = false;
140
180 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); 141 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
142 child.ClearDisplacement();
181 if (IsRoot(child)) 143 if (IsRoot(child))
182 { 144 {
183 ScheduleRebuild(LinksetRoot); 145 // Schedule a rebuild to verify that the root shape is set to the real shape.
184 } 146 Refresh(LinksetRoot);
185 else
186 {
187 // The non-physical children can come back to life.
188 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
189
190 child.PhysBody.collisionType = CollisionType.LinksetChild;
191
192 // Don't force activation so setting of DISABLE_SIMULATION can stay if used.
193 PhysicsScene.PE.Activate(child.PhysBody, false);
194 ret = true;
195 } 147 }
196 return ret; 148 return ret;
197 } 149 }
@@ -200,13 +152,20 @@ public sealed class BSLinksetCompound : BSLinkset
200 // Called at taint-time. 152 // Called at taint-time.
201 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated) 153 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated)
202 { 154 {
155 if (!LinksetRoot.IsPhysicallyActive)
156 {
157 // No reason to do this physical stuff for static linksets.
158 DetailLog("{0},BSLinksetCompound.UpdateProperties,notPhysical", LinksetRoot.LocalID);
159 return;
160 }
161
203 // The user moving a child around requires the rebuilding of the linkset compound shape 162 // The user moving a child around requires the rebuilding of the linkset compound shape
204 // One problem is this happens when a border is crossed -- the simulator implementation 163 // One problem is this happens when a border is crossed -- the simulator implementation
205 // stores the position into the group which causes the move of the object 164 // stores the position into the group which causes the move of the object
206 // but it also means all the child positions get updated. 165 // but it also means all the child positions get updated.
207 // What would cause an unnecessary rebuild so we make sure the linkset is in a 166 // What would cause an unnecessary rebuild so we make sure the linkset is in a
208 // region before bothering to do a rebuild. 167 // region before bothering to do a rebuild.
209 if (!IsRoot(updated) && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition)) 168 if (!IsRoot(updated) && m_physicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
210 { 169 {
211 // If a child of the linkset is updating only the position or rotation, that can be done 170 // If a child of the linkset is updating only the position or rotation, that can be done
212 // without rebuilding the linkset. 171 // without rebuilding the linkset.
@@ -218,22 +177,22 @@ public sealed class BSLinksetCompound : BSLinkset
218 // and that is caused by us updating the object. 177 // and that is caused by us updating the object.
219 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) 178 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
220 { 179 {
221 // Find the physical instance of the child 180 // Find the physical instance of the child
222 if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) 181 if (LinksetRoot.PhysShape.HasPhysicalShape && m_physicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
223 { 182 {
224 // It is possible that the linkset is still under construction and the child is not yet 183 // It is possible that the linkset is still under construction and the child is not yet
225 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will 184 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
226 // build the whole thing with the new position or rotation. 185 // build the whole thing with the new position or rotation.
227 // The index must be checked because Bullet references the child array but does no validity 186 // The index must be checked because Bullet references the child array but does no validity
228 // checking of the child index passed. 187 // checking of the child index passed.
229 int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); 188 int numLinksetChildren = m_physicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape.physShapeInfo);
230 if (updated.LinksetChildIndex < numLinksetChildren) 189 if (updated.LinksetChildIndex < numLinksetChildren)
231 { 190 {
232 BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex); 191 BulletShape linksetChildShape = m_physicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex);
233 if (linksetChildShape.HasPhysicalShape) 192 if (linksetChildShape.HasPhysicalShape)
234 { 193 {
235 // Found the child shape within the compound shape 194 // Found the child shape within the compound shape
236 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex, 195 m_physicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex,
237 updated.RawPosition - LinksetRoot.RawPosition, 196 updated.RawPosition - LinksetRoot.RawPosition,
238 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation), 197 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
239 true /* shouldRecalculateLocalAabb */); 198 true /* shouldRecalculateLocalAabb */);
@@ -267,83 +226,29 @@ public sealed class BSLinksetCompound : BSLinkset
267 // there will already be a rebuild scheduled. 226 // there will already be a rebuild scheduled.
268 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}", 227 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}",
269 updated.LocalID, whichUpdated); 228 updated.LocalID, whichUpdated);
270 updated.LinksetInfo = null; // setting to 'null' causes relative position to be recomputed. 229 Refresh(updated);
271 ScheduleRebuild(updated);
272 } 230 }
273 } 231 }
274 } 232 }
275 } 233 }
276 234
277 // Routine called when rebuilding the body of some member of the linkset. 235 // Routine called when rebuilding the body of some member of the linkset.
278 // Since we don't keep in world relationships, do nothing unless it's a child changing. 236 // If one of the bodies is being changed, the linkset needs rebuilding.
237 // For instance, a linkset is built and then a mesh asset is read in and the mesh is recreated.
279 // Returns 'true' of something was actually removed and would need restoring 238 // Returns 'true' of something was actually removed and would need restoring
280 // Called at taint-time!! 239 // Called at taint-time!!
281 public override bool RemoveBodyDependencies(BSPrimLinkable child) 240 public override bool RemoveDependencies(BSPrimLinkable child)
282 { 241 {
283 bool ret = false; 242 bool ret = false;
284 243
285 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", 244 DetailLog("{0},BSLinksetCompound.RemoveDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
286 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child)); 245 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child));
287 246
288 if (!IsRoot(child)) 247 Refresh(child);
289 {
290 // Because it is a convenient time, recompute child world position and rotation based on
291 // its position in the linkset.
292 RecomputeChildWorldPosition(child, true /* inTaintTime */);
293 child.LinksetInfo = null;
294 }
295
296 // Cannot schedule a refresh/rebuild here because this routine is called when
297 // the linkset is being rebuilt.
298 // InternalRefresh(LinksetRoot);
299 248
300 return ret; 249 return ret;
301 } 250 }
302 251
303 // When the linkset is built, the child shape is added to the compound shape relative to the
304 // root shape. The linkset then moves around but this does not move the actual child
305 // prim. The child prim's location must be recomputed based on the location of the root shape.
306 private void RecomputeChildWorldPosition(BSPrimLinkable child, bool inTaintTime)
307 {
308 // For the moment (20130201), disable this computation (converting the child physical addr back to
309 // a region address) until we have a good handle on center-of-mass offsets and what the physics
310 // engine moving a child actually means.
311 // The simulator keeps track of where children should be as the linkset moves. Setting
312 // the pos/rot here does not effect that knowledge as there is no good way for the
313 // physics engine to send the simulator an update for a child.
314
315 /*
316 BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
317 if (lci != null)
318 {
319 if (inTaintTime)
320 {
321 OMV.Vector3 oldPos = child.RawPosition;
322 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetFromRoot;
323 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
324 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
325 child.LocalID, oldPos, lci, child.RawPosition);
326 }
327 else
328 {
329 // TaintedObject is not used here so the raw position is set now and not at taint-time.
330 child.Position = LinksetRoot.RawPosition + lci.OffsetFromRoot;
331 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
332 }
333 }
334 else
335 {
336 // This happens when children have been added to the linkset but the linkset
337 // has not been constructed yet. So like, at taint time, adding children to a linkset
338 // and then changing properties of the children (makePhysical, for instance)
339 // but the post-print action of actually rebuilding the linkset has not yet happened.
340 // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}",
341 // LogHeader, child.LocalID);
342 DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
343 }
344 */
345 }
346
347 // ================================================================ 252 // ================================================================
348 253
349 // Add a new child to the linkset. 254 // Add a new child to the linkset.
@@ -352,19 +257,19 @@ public sealed class BSLinksetCompound : BSLinkset
352 { 257 {
353 if (!HasChild(child)) 258 if (!HasChild(child))
354 { 259 {
355 m_children.Add(child); 260 m_children.Add(child, new BSLinkInfo(child));
356 261
357 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 262 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
358 263
359 // Rebuild the compound shape with the new child shape included 264 // Rebuild the compound shape with the new child shape included
360 ScheduleRebuild(child); 265 Refresh(child);
361 } 266 }
362 return; 267 return;
363 } 268 }
364 269
365 // Remove the specified child from the linkset. 270 // Remove the specified child from the linkset.
366 // Safe to call even if the child is not really in the linkset. 271 // Safe to call even if the child is not really in the linkset.
367 protected override void RemoveChildFromLinkset(BSPrimLinkable child) 272 protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
368 { 273 {
369 child.ClearDisplacement(); 274 child.ClearDisplacement();
370 275
@@ -376,19 +281,17 @@ public sealed class BSLinksetCompound : BSLinkset
376 child.LocalID, child.PhysBody.AddrString); 281 child.LocalID, child.PhysBody.AddrString);
377 282
378 // Cause the child's body to be rebuilt and thus restored to normal operation 283 // Cause the child's body to be rebuilt and thus restored to normal operation
379 RecomputeChildWorldPosition(child, false); 284 child.ForceBodyShapeRebuild(inTaintTime);
380 child.LinksetInfo = null;
381 child.ForceBodyShapeRebuild(false);
382 285
383 if (!HasAnyChildren) 286 if (!HasAnyChildren)
384 { 287 {
385 // The linkset is now empty. The root needs rebuilding. 288 // The linkset is now empty. The root needs rebuilding.
386 LinksetRoot.ForceBodyShapeRebuild(false); 289 LinksetRoot.ForceBodyShapeRebuild(inTaintTime);
387 } 290 }
388 else 291 else
389 { 292 {
390 // Rebuild the compound shape with the child removed 293 // Rebuild the compound shape with the child removed
391 ScheduleRebuild(LinksetRoot); 294 Refresh(LinksetRoot);
392 } 295 }
393 } 296 }
394 return; 297 return;
@@ -399,108 +302,118 @@ public sealed class BSLinksetCompound : BSLinkset
399 // Constraint linksets are rebuilt every time. 302 // Constraint linksets are rebuilt every time.
400 // Note that this works for rebuilding just the root after a linkset is taken apart. 303 // Note that this works for rebuilding just the root after a linkset is taken apart.
401 // Called at taint time!! 304 // Called at taint time!!
402 private bool disableCOM = true; // DEBUG DEBUG: disable until we get this debugged 305 private bool UseBulletSimRootOffsetHack = false; // Attempt to have Bullet track the coords of root compound shape
403 private void RecomputeLinksetCompound() 306 private void RecomputeLinksetCompound()
404 { 307 {
405 try 308 try
406 { 309 {
407 // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.)
408 Rebuilding = true; 310 Rebuilding = true;
409 311
410 // Cause the root shape to be rebuilt as a compound object with just the root in it 312 // No matter what is being done, force the root prim's PhysBody and PhysShape to get set
411 LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime */); 313 // to what they should be as if the root was not in a linkset.
314 // Not that bad since we only get into this routine if there are children in the linkset and
315 // something has been updated/changed.
316 // Have to do the rebuild before checking for physical because this might be a linkset
317 // being destructed and going non-physical.
318 LinksetRoot.ForceBodyShapeRebuild(true);
412 319
413 // The center of mass for the linkset is the geometric center of the group. 320 // There is no reason to build all this physical stuff for a non-physical or empty linkset.
414 // Compute a displacement for each component so it is relative to the center-of-mass. 321 if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
415 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
416 OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition;
417 if (!disableCOM) // DEBUG DEBUG
418 { 322 {
419 // Compute a center-of-mass in world coordinates. 323 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
420 centerOfMassW = ComputeLinksetCenterOfMass(); 324 return; // Note the 'finally' clause at the botton which will get executed.
421 } 325 }
422 326
423 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); 327 // Get a new compound shape to build the linkset shape in.
424 328 BSShape linksetShape = BSShapeCompound.GetReference(m_physicsScene);
425 // 'centerDisplacement' is the value to subtract from children to give physical offset position
426 OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
427 LinksetRoot.SetEffectiveCenterOfMassW(centerDisplacement);
428 329
429 // This causes the physical position of the root prim to be offset to accomodate for the displacements 330 // Compute a displacement for each component so it is relative to the center-of-mass.
430 LinksetRoot.ForcePosition = LinksetRoot.RawPosition; 331 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
332 OMV.Vector3 centerOfMassW = ComputeLinksetCenterOfMass();
431 333
432 // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM 334 OMV.Quaternion invRootOrientation = OMV.Quaternion.Normalize(OMV.Quaternion.Inverse(LinksetRoot.RawOrientation));
433 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */, 335 OMV.Vector3 origRootPosition = LinksetRoot.RawPosition;
434 -centerDisplacement,
435 OMV.Quaternion.Identity, // LinksetRoot.RawOrientation,
436 false /* shouldRecalculateLocalAabb (is done later after linkset built) */);
437 336
438 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}", 337 // 'centerDisplacementV' is the vehicle relative distance from the simulator root position to the center-of-mass
439 LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement); 338 OMV.Vector3 centerDisplacementV = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
339 if (UseBulletSimRootOffsetHack || !BSParam.LinksetOffsetCenterOfMass)
340 {
341 // Zero everything if center-of-mass displacement is not being done.
342 centerDisplacementV = OMV.Vector3.Zero;
343 LinksetRoot.ClearDisplacement();
344 }
345 else
346 {
347 // The actual center-of-mass could have been set by the user.
348 centerDisplacementV = LinksetRoot.SetEffectiveCenterOfMassDisplacement(centerDisplacementV);
349 }
440 350
441 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", 351 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,rootPos={1},com={2},comDisp={3}",
442 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); 352 LinksetRoot.LocalID, origRootPosition, centerOfMassW, centerDisplacementV);
443 353
444 // Add a shape for each of the other children in the linkset 354 // Add the shapes of all the components of the linkset
445 int memberIndex = 1; 355 int memberIndex = 1;
446 ForEachMember(delegate(BSPrimLinkable cPrim) 356 ForEachMember((cPrim) =>
447 { 357 {
448 if (IsRoot(cPrim)) 358 if (IsRoot(cPrim))
449 { 359 {
360 // Root shape is always index zero.
450 cPrim.LinksetChildIndex = 0; 361 cPrim.LinksetChildIndex = 0;
451 } 362 }
452 else 363 else
453 { 364 {
454 cPrim.LinksetChildIndex = memberIndex; 365 cPrim.LinksetChildIndex = memberIndex;
366 memberIndex++;
367 }
455 368
456 if (cPrim.PhysShape.isNativeShape) 369 // Get a reference to the shape of the child for adding of that shape to the linkset compound shape
457 { 370 BSShape childShape = cPrim.PhysShape.GetReference(m_physicsScene, cPrim);
458 // A native shape is turned into a hull collision shape because native
459 // shapes are not shared so we have to hullify it so it will be tracked
460 // and freed at the correct time. This also solves the scaling problem
461 // (native shapes scale but hull/meshes are assumed to not be).
462 // TODO: decide of the native shape can just be used in the compound shape.
463 // Use call to CreateGeomNonSpecial().
464 BulletShape saveShape = cPrim.PhysShape;
465 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
466 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
467 BulletShape newShape = cPrim.PhysShape;
468 cPrim.PhysShape = saveShape;
469
470 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
471 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
472 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
473 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
474 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
475 }
476 else
477 {
478 // For the shared shapes (meshes and hulls), just use the shape in the child.
479 // The reference count added here will be decremented when the compound shape
480 // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
481 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
482 {
483 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
484 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
485 }
486 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
487 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
488 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
489 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
490 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
491 371
492 } 372 // Offset the child shape from the center-of-mass and rotate it to vehicle relative.
493 memberIndex++; 373 OMV.Vector3 offsetPos = (cPrim.RawPosition - origRootPosition) * invRootOrientation - centerDisplacementV;
374 OMV.Quaternion offsetRot = OMV.Quaternion.Normalize(cPrim.RawOrientation) * invRootOrientation;
375
376 // Add the child shape to the compound shape being built
377 m_physicsScene.PE.AddChildShapeToCompoundShape(linksetShape.physShapeInfo, childShape.physShapeInfo, offsetPos, offsetRot);
378 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addChild,indx={1},cShape={2},offPos={3},offRot={4}",
379 LinksetRoot.LocalID, cPrim.LinksetChildIndex, childShape, offsetPos, offsetRot);
380
381 // Since we are borrowing the shape of the child, disable the origional child body
382 if (!IsRoot(cPrim))
383 {
384 m_physicsScene.PE.AddToCollisionFlags(cPrim.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
385 m_physicsScene.PE.ForceActivationState(cPrim.PhysBody, ActivationState.DISABLE_SIMULATION);
386 // We don't want collisions from the old linkset children.
387 m_physicsScene.PE.RemoveFromCollisionFlags(cPrim.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
388 cPrim.PhysBody.collisionType = CollisionType.LinksetChild;
494 } 389 }
390
495 return false; // 'false' says to move onto the next child in the list 391 return false; // 'false' says to move onto the next child in the list
496 }); 392 });
497 393
394 // Replace the root shape with the built compound shape.
395 // Object removed and added to world to get collision cache rebuilt for new shape.
396 LinksetRoot.PhysShape.Dereference(m_physicsScene);
397 LinksetRoot.PhysShape = linksetShape;
398 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, LinksetRoot.PhysBody);
399 m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, LinksetRoot.PhysBody, linksetShape.physShapeInfo);
400 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, LinksetRoot.PhysBody);
401 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addBody,body={1},shape={2}",
402 LinksetRoot.LocalID, LinksetRoot.PhysBody, linksetShape);
403
498 // With all of the linkset packed into the root prim, it has the mass of everyone. 404 // With all of the linkset packed into the root prim, it has the mass of everyone.
499 LinksetMass = ComputeLinksetMass(); 405 LinksetMass = ComputeLinksetMass();
500 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); 406 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
501 407
502 // Enable the physical position updator to return the position and rotation of the root shape 408 if (UseBulletSimRootOffsetHack)
503 PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE); 409 {
410 // Enable the physical position updator to return the position and rotation of the root shape.
411 // This enables a feature in the C++ code to return the world coordinates of the first shape in the
412 // compound shape. This aleviates the need to offset the returned physical position by the
413 // center-of-mass offset.
414 // TODO: either debug this feature or remove it.
415 m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
416 }
504 } 417 }
505 finally 418 finally
506 { 419 {
@@ -508,7 +421,7 @@ public sealed class BSLinksetCompound : BSLinkset
508 } 421 }
509 422
510 // See that the Aabb surrounds the new shape 423 // See that the Aabb surrounds the new shape
511 PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); 424 m_physicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo);
512 } 425 }
513} 426}
514} \ No newline at end of file 427} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index 6d252ca..aaf92c8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -28,6 +28,8 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30 30
31using OpenSim.Region.OptionalModules.Scripting;
32
31using OMV = OpenMetaverse; 33using OMV = OpenMetaverse;
32 34
33namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
@@ -36,26 +38,194 @@ public sealed class BSLinksetConstraints : BSLinkset
36{ 38{
37 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; 39 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
38 40
41 public class BSLinkInfoConstraint : BSLinkInfo
42 {
43 public ConstraintType constraintType;
44 public BSConstraint constraint;
45 public OMV.Vector3 linearLimitLow;
46 public OMV.Vector3 linearLimitHigh;
47 public OMV.Vector3 angularLimitLow;
48 public OMV.Vector3 angularLimitHigh;
49 public bool useFrameOffset;
50 public bool enableTransMotor;
51 public float transMotorMaxVel;
52 public float transMotorMaxForce;
53 public float cfm;
54 public float erp;
55 public float solverIterations;
56 //
57 public OMV.Vector3 frameInAloc;
58 public OMV.Quaternion frameInArot;
59 public OMV.Vector3 frameInBloc;
60 public OMV.Quaternion frameInBrot;
61 public bool useLinearReferenceFrameA;
62 // Spring
63 public bool[] springAxisEnable;
64 public float[] springDamping;
65 public float[] springStiffness;
66 public OMV.Vector3 springLinearEquilibriumPoint;
67 public OMV.Vector3 springAngularEquilibriumPoint;
68
69 public BSLinkInfoConstraint(BSPrimLinkable pMember)
70 : base(pMember)
71 {
72 constraint = null;
73 ResetLink();
74 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.creation", member.LocalID);
75 }
76
77 // Set all the parameters for this constraint to a fixed, non-movable constraint.
78 public override void ResetLink()
79 {
80 // constraintType = ConstraintType.D6_CONSTRAINT_TYPE;
81 constraintType = ConstraintType.FIXED_CONSTRAINT_TYPE;
82 linearLimitLow = OMV.Vector3.Zero;
83 linearLimitHigh = OMV.Vector3.Zero;
84 angularLimitLow = OMV.Vector3.Zero;
85 angularLimitHigh = OMV.Vector3.Zero;
86 useFrameOffset = BSParam.LinkConstraintUseFrameOffset;
87 enableTransMotor = BSParam.LinkConstraintEnableTransMotor;
88 transMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
89 transMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
90 cfm = BSParam.LinkConstraintCFM;
91 erp = BSParam.LinkConstraintERP;
92 solverIterations = BSParam.LinkConstraintSolverIterations;
93 frameInAloc = OMV.Vector3.Zero;
94 frameInArot = OMV.Quaternion.Identity;
95 frameInBloc = OMV.Vector3.Zero;
96 frameInBrot = OMV.Quaternion.Identity;
97 useLinearReferenceFrameA = true;
98 springAxisEnable = new bool[6];
99 springDamping = new float[6];
100 springStiffness = new float[6];
101 for (int ii = 0; ii < springAxisEnable.Length; ii++)
102 {
103 springAxisEnable[ii] = false;
104 springDamping[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
105 springStiffness[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
106 }
107 springLinearEquilibriumPoint = OMV.Vector3.Zero;
108 springAngularEquilibriumPoint = OMV.Vector3.Zero;
109 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.ResetLink", member.LocalID);
110 }
111
112 // Given a constraint, apply the current constraint parameters to same.
113 public override void SetLinkParameters(BSConstraint constrain)
114 {
115 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.SetLinkParameters,type={1}", member.LocalID, constraintType);
116 switch (constraintType)
117 {
118 case ConstraintType.FIXED_CONSTRAINT_TYPE:
119 case ConstraintType.D6_CONSTRAINT_TYPE:
120 BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof;
121 if (constrain6dof != null)
122 {
123 // NOTE: D6_SPRING_CONSTRAINT_TYPE should be updated if you change any of this code.
124 // zero linear and angular limits makes the objects unable to move in relation to each other
125 constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh);
126 constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh);
127
128 // tweek the constraint to increase stability
129 constrain6dof.UseFrameOffset(useFrameOffset);
130 constrain6dof.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
131 constrain6dof.SetCFMAndERP(cfm, erp);
132 if (solverIterations != 0f)
133 {
134 constrain6dof.SetSolverIterations(solverIterations);
135 }
136 }
137 break;
138 case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
139 BSConstraintSpring constrainSpring = constrain as BSConstraintSpring;
140 if (constrainSpring != null)
141 {
142 // zero linear and angular limits makes the objects unable to move in relation to each other
143 constrainSpring.SetLinearLimits(linearLimitLow, linearLimitHigh);
144 constrainSpring.SetAngularLimits(angularLimitLow, angularLimitHigh);
145
146 // tweek the constraint to increase stability
147 constrainSpring.UseFrameOffset(useFrameOffset);
148 constrainSpring.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
149 constrainSpring.SetCFMAndERP(cfm, erp);
150 if (solverIterations != 0f)
151 {
152 constrainSpring.SetSolverIterations(solverIterations);
153 }
154 for (int ii = 0; ii < springAxisEnable.Length; ii++)
155 {
156 constrainSpring.SetAxisEnable(ii, springAxisEnable[ii]);
157 if (springDamping[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
158 constrainSpring.SetDamping(ii, springDamping[ii]);
159 if (springStiffness[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
160 constrainSpring.SetStiffness(ii, springStiffness[ii]);
161 }
162 constrainSpring.CalculateTransforms();
163
164 if (springLinearEquilibriumPoint != OMV.Vector3.Zero)
165 constrainSpring.SetEquilibriumPoint(springLinearEquilibriumPoint, springAngularEquilibriumPoint);
166 else
167 constrainSpring.SetEquilibriumPoint(BSAPITemplate.SPRING_NOT_SPECIFIED, BSAPITemplate.SPRING_NOT_SPECIFIED);
168 }
169 break;
170 default:
171 break;
172 }
173 }
174
175 // Return 'true' if the property updates from the physics engine should be reported
176 // to the simulator.
177 // If the constraint is fixed, we don't need to report as the simulator and viewer will
178 // report the right things.
179 public override bool ShouldUpdateChildProperties()
180 {
181 bool ret = true;
182 if (constraintType == ConstraintType.FIXED_CONSTRAINT_TYPE)
183 ret = false;
184
185 return ret;
186 }
187 }
188
39 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent) 189 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
40 { 190 {
191 LinksetImpl = LinksetImplementation.Constraint;
41 } 192 }
42 193
194 private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINT]";
195
43 // When physical properties are changed the linkset needs to recalculate 196 // When physical properties are changed the linkset needs to recalculate
44 // its internal properties. 197 // its internal properties.
45 // This is queued in the 'post taint' queue so the 198 // This is queued in the 'post taint' queue so the
46 // refresh will happen once after all the other taints are applied. 199 // refresh will happen once after all the other taints are applied.
47 public override void Refresh(BSPrimLinkable requestor) 200 public override void Refresh(BSPrimLinkable requestor)
48 { 201 {
202 ScheduleRebuild(requestor);
49 base.Refresh(requestor); 203 base.Refresh(requestor);
50 204
51 if (HasAnyChildren && IsRoot(requestor)) 205 }
206
207 private void ScheduleRebuild(BSPrimLinkable requestor)
208 {
209 DetailLog("{0},BSLinksetConstraint.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}",
210 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren));
211
212 // When rebuilding, it is possible to set properties that would normally require a rebuild.
213 // If already rebuilding, don't request another rebuild.
214 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
215 if (!Rebuilding && HasAnyChildren)
52 { 216 {
53 // Queue to happen after all the other taint processing 217 // Queue to happen after all the other taint processing
54 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() 218 m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
219 {
220 if (HasAnyChildren)
55 { 221 {
56 if (HasAnyChildren && IsRoot(requestor)) 222 // Constraints that have not been changed are not rebuild but make sure
57 RecomputeLinksetConstraints(); 223 // the constraint of the requestor is rebuilt.
58 }); 224 PhysicallyUnlinkAChildFromRoot(LinksetRoot, requestor);
225 // Rebuild the linkset and all its constraints.
226 RecomputeLinksetConstraints();
227 }
228 });
59 } 229 }
60 } 230 }
61 231
@@ -67,8 +237,14 @@ public sealed class BSLinksetConstraints : BSLinkset
67 // Called at taint-time! 237 // Called at taint-time!
68 public override bool MakeDynamic(BSPrimLinkable child) 238 public override bool MakeDynamic(BSPrimLinkable child)
69 { 239 {
70 // What is done for each object in BSPrim is what we want. 240 bool ret = false;
71 return false; 241 DetailLog("{0},BSLinksetConstraints.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
242 if (IsRoot(child))
243 {
244 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
245 Refresh(LinksetRoot);
246 }
247 return ret;
72 } 248 }
73 249
74 // The object is going static (non-physical). Do any setup necessary for a static linkset. 250 // The object is going static (non-physical). Do any setup necessary for a static linkset.
@@ -78,8 +254,16 @@ public sealed class BSLinksetConstraints : BSLinkset
78 // Called at taint-time! 254 // Called at taint-time!
79 public override bool MakeStatic(BSPrimLinkable child) 255 public override bool MakeStatic(BSPrimLinkable child)
80 { 256 {
81 // What is done for each object in BSPrim is what we want. 257 bool ret = false;
82 return false; 258
259 DetailLog("{0},BSLinksetConstraint.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
260 child.ClearDisplacement();
261 if (IsRoot(child))
262 {
263 // Schedule a rebuild to verify that the root shape is set to the real shape.
264 Refresh(LinksetRoot);
265 }
266 return ret;
83 } 267 }
84 268
85 // Called at taint-time!! 269 // Called at taint-time!!
@@ -93,11 +277,11 @@ public sealed class BSLinksetConstraints : BSLinkset
93 // up to rebuild the constraints before the next simulation step. 277 // up to rebuild the constraints before the next simulation step.
94 // Returns 'true' of something was actually removed and would need restoring 278 // Returns 'true' of something was actually removed and would need restoring
95 // Called at taint-time!! 279 // Called at taint-time!!
96 public override bool RemoveBodyDependencies(BSPrimLinkable child) 280 public override bool RemoveDependencies(BSPrimLinkable child)
97 { 281 {
98 bool ret = false; 282 bool ret = false;
99 283
100 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", 284 DetailLog("{0},BSLinksetConstraint.RemoveDependencies,removeChildrenForRoot,rID={1},rBody={2}",
101 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString); 285 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString);
102 286
103 lock (m_linksetActivityLock) 287 lock (m_linksetActivityLock)
@@ -118,7 +302,7 @@ public sealed class BSLinksetConstraints : BSLinkset
118 { 302 {
119 if (!HasChild(child)) 303 if (!HasChild(child))
120 { 304 {
121 m_children.Add(child); 305 m_children.Add(child, new BSLinkInfoConstraint(child));
122 306
123 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 307 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
124 308
@@ -130,7 +314,7 @@ public sealed class BSLinksetConstraints : BSLinkset
130 314
131 // Remove the specified child from the linkset. 315 // Remove the specified child from the linkset.
132 // Safe to call even if the child is not really in my linkset. 316 // Safe to call even if the child is not really in my linkset.
133 protected override void RemoveChildFromLinkset(BSPrimLinkable child) 317 protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
134 { 318 {
135 if (m_children.Remove(child)) 319 if (m_children.Remove(child))
136 { 320 {
@@ -142,7 +326,7 @@ public sealed class BSLinksetConstraints : BSLinkset
142 rootx.LocalID, rootx.PhysBody.AddrString, 326 rootx.LocalID, rootx.PhysBody.AddrString,
143 childx.LocalID, childx.PhysBody.AddrString); 327 childx.LocalID, childx.PhysBody.AddrString);
144 328
145 PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() 329 m_physicsScene.TaintedObject(inTaintTime, childx.LocalID, "BSLinksetConstraints.RemoveChildFromLinkset", delegate()
146 { 330 {
147 PhysicallyUnlinkAChildFromRoot(rootx, childx); 331 PhysicallyUnlinkAChildFromRoot(rootx, childx);
148 }); 332 });
@@ -165,73 +349,86 @@ public sealed class BSLinksetConstraints : BSLinkset
165 Refresh(rootPrim); 349 Refresh(rootPrim);
166 } 350 }
167 351
168 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSPrimLinkable childPrim) 352 // Create a static constraint between the two passed objects
353 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
169 { 354 {
355 BSLinkInfoConstraint linkInfo = li as BSLinkInfoConstraint;
356 if (linkInfo == null)
357 return null;
358
170 // Zero motion for children so they don't interpolate 359 // Zero motion for children so they don't interpolate
171 childPrim.ZeroMotion(true); 360 li.member.ZeroMotion(true);
172 361
173 // Relative position normalized to the root prim 362 BSConstraint constrain = null;
174 // Essentually a vector pointing from center of rootPrim to center of childPrim 363
175 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; 364 switch (linkInfo.constraintType)
176
177 // real world coordinate of midpoint between the two objects
178 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
179
180 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
181 rootPrim.LocalID,
182 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
183 childPrim.LocalID, childPrim.PhysBody.AddrString,
184 rootPrim.Position, childPrim.Position, midPoint);
185
186 // create a constraint that allows no freedom of movement between the two objects
187 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
188
189 BSConstraint6Dof constrain = new BSConstraint6Dof(
190 PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
191 // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );
192
193 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
194 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
195 * of the objects.
196 * Code left for future programmers.
197 // ==================================================================================
198 // relative position normalized to the root prim
199 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
200 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
201
202 // relative rotation of the child to the parent
203 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
204 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
205
206 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
207 BS6DofConstraint constrain = new BS6DofConstraint(
208 PhysicsScene.World, rootPrim.Body, childPrim.Body,
209 OMV.Vector3.Zero,
210 OMV.Quaternion.Inverse(rootPrim.Orientation),
211 OMV.Vector3.Zero,
212 OMV.Quaternion.Inverse(childPrim.Orientation),
213 true,
214 true
215 );
216 // ==================================================================================
217 */
218
219 PhysicsScene.Constraints.AddConstraint(constrain);
220
221 // zero linear and angular limits makes the objects unable to move in relation to each other
222 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
223 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
224
225 // tweek the constraint to increase stability
226 constrain.UseFrameOffset(BSParam.LinkConstraintUseFrameOffset);
227 constrain.TranslationalLimitMotor(BSParam.LinkConstraintEnableTransMotor,
228 BSParam.LinkConstraintTransMotorMaxVel,
229 BSParam.LinkConstraintTransMotorMaxForce);
230 constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
231 if (BSParam.LinkConstraintSolverIterations != 0f)
232 { 365 {
233 constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations); 366 case ConstraintType.FIXED_CONSTRAINT_TYPE:
367 case ConstraintType.D6_CONSTRAINT_TYPE:
368 // Relative position normalized to the root prim
369 // Essentually a vector pointing from center of rootPrim to center of li.member
370 OMV.Vector3 childRelativePosition = linkInfo.member.Position - rootPrim.Position;
371
372 // real world coordinate of midpoint between the two objects
373 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
374
375 DetailLog("{0},BSLinksetConstraint.BuildConstraint,6Dof,rBody={1},cBody={2},rLoc={3},cLoc={4},midLoc={5}",
376 rootPrim.LocalID, rootPrim.PhysBody, linkInfo.member.PhysBody,
377 rootPrim.Position, linkInfo.member.Position, midPoint);
378
379 // create a constraint that allows no freedom of movement between the two objects
380 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
381
382 constrain = new BSConstraint6Dof(
383 m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody, midPoint, true, true );
384
385 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
386 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
387 * of the objects.
388 * Code left for future programmers.
389 // ==================================================================================
390 // relative position normalized to the root prim
391 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
392 OMV.Vector3 childRelativePosition = (liConstraint.member.Position - rootPrim.Position) * invThisOrientation;
393
394 // relative rotation of the child to the parent
395 OMV.Quaternion childRelativeRotation = invThisOrientation * liConstraint.member.Orientation;
396 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
397
398 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, liConstraint.member.LocalID);
399 constrain = new BS6DofConstraint(
400 PhysicsScene.World, rootPrim.Body, liConstraint.member.Body,
401 OMV.Vector3.Zero,
402 OMV.Quaternion.Inverse(rootPrim.Orientation),
403 OMV.Vector3.Zero,
404 OMV.Quaternion.Inverse(liConstraint.member.Orientation),
405 true,
406 true
407 );
408 // ==================================================================================
409 */
410
411 break;
412 case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
413 constrain = new BSConstraintSpring(m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody,
414 linkInfo.frameInAloc, linkInfo.frameInArot, linkInfo.frameInBloc, linkInfo.frameInBrot,
415 linkInfo.useLinearReferenceFrameA,
416 true /*disableCollisionsBetweenLinkedBodies*/);
417 DetailLog("{0},BSLinksetConstraint.BuildConstraint,spring,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6}",
418 rootPrim.LocalID,
419 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
420 linkInfo.member.LocalID, linkInfo.member.PhysBody.AddrString,
421 rootPrim.Position, linkInfo.member.Position);
422
423 break;
424 default:
425 break;
234 } 426 }
427
428 linkInfo.SetLinkParameters(constrain);
429
430 m_physicsScene.Constraints.AddConstraint(constrain);
431
235 return constrain; 432 return constrain;
236 } 433 }
237 434
@@ -247,13 +444,22 @@ public sealed class BSLinksetConstraints : BSLinkset
247 rootPrim.LocalID, rootPrim.PhysBody.AddrString, 444 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
248 childPrim.LocalID, childPrim.PhysBody.AddrString); 445 childPrim.LocalID, childPrim.PhysBody.AddrString);
249 446
250 // Find the constraint for this link and get rid of it from the overall collection and from my list 447 // If asked to unlink root from root, just remove all the constraints
251 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) 448 if (rootPrim == childPrim || childPrim == LinksetRoot)
252 { 449 {
253 // Make the child refresh its location 450 PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
254 PhysicsScene.PE.PushUpdate(childPrim.PhysBody);
255 ret = true; 451 ret = true;
256 } 452 }
453 else
454 {
455 // Find the constraint for this link and get rid of it from the overall collection and from my list
456 if (m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
457 {
458 // Make the child refresh its location
459 m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
460 ret = true;
461 }
462 }
257 463
258 return ret; 464 return ret;
259 } 465 }
@@ -265,7 +471,7 @@ public sealed class BSLinksetConstraints : BSLinkset
265 { 471 {
266 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 472 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
267 473
268 return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); 474 return m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody);
269 } 475 }
270 476
271 // Call each of the constraints that make up this linkset and recompute the 477 // Call each of the constraints that make up this linkset and recompute the
@@ -281,24 +487,360 @@ public sealed class BSLinksetConstraints : BSLinkset
281 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", 487 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}",
282 LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass); 488 LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass);
283 489
284 foreach (BSPrimLinkable child in m_children) 490 try
285 { 491 {
286 // A child in the linkset physically shows the mass of the whole linkset. 492 Rebuilding = true;
287 // This allows Bullet to apply enough force on the child to move the whole linkset.
288 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
289 child.UpdatePhysicalMassProperties(linksetMass, true);
290 493
291 BSConstraint constrain; 494 // There is no reason to build all this physical stuff for a non-physical linkset.
292 if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) 495 if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
293 { 496 {
294 // If constraint doesn't exist yet, create it. 497 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
295 constrain = BuildConstraint(LinksetRoot, child); 498 return; // Note the 'finally' clause at the botton which will get executed.
296 } 499 }
297 constrain.RecomputeConstraintVariables(linksetMass);
298 500
299 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG 501 ForEachLinkInfo((li) =>
502 {
503 // A child in the linkset physically shows the mass of the whole linkset.
504 // This allows Bullet to apply enough force on the child to move the whole linkset.
505 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
506 li.member.UpdatePhysicalMassProperties(linksetMass, true);
507
508 BSConstraint constrain;
509 if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, li.member.PhysBody, out constrain))
510 {
511 // If constraint doesn't exist yet, create it.
512 constrain = BuildConstraint(LinksetRoot, li);
513 }
514 li.SetLinkParameters(constrain);
515 constrain.RecomputeConstraintVariables(linksetMass);
516
517 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
518 return false; // 'false' says to keep processing other members
519 });
300 } 520 }
521 finally
522 {
523 Rebuilding = false;
524 }
525 }
301 526
527 #region Extension
528 public override object Extension(string pFunct, params object[] pParams)
529 {
530 object ret = null;
531 switch (pFunct)
532 {
533 // pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
534 case ExtendedPhysics.PhysFunctChangeLinkType:
535 if (pParams.Length > 2)
536 {
537 int requestedType = (int)pParams[2];
538 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,requestedType={1}", LinksetRoot.LocalID, requestedType);
539 if (requestedType == (int)ConstraintType.FIXED_CONSTRAINT_TYPE
540 || requestedType == (int)ConstraintType.D6_CONSTRAINT_TYPE
541 || requestedType == (int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE
542 || requestedType == (int)ConstraintType.HINGE_CONSTRAINT_TYPE
543 || requestedType == (int)ConstraintType.CONETWIST_CONSTRAINT_TYPE
544 || requestedType == (int)ConstraintType.SLIDER_CONSTRAINT_TYPE)
545 {
546 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
547 if (child != null)
548 {
549 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,rootID={1},childID={2},type={3}",
550 LinksetRoot.LocalID, LinksetRoot.LocalID, child.LocalID, requestedType);
551 m_physicsScene.TaintedObject(child.LocalID, "BSLinksetConstraint.PhysFunctChangeLinkType", delegate()
552 {
553 // Pick up all the constraints currently created.
554 RemoveDependencies(child);
555
556 BSLinkInfo linkInfo = null;
557 if (TryGetLinkInfo(child, out linkInfo))
558 {
559 BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
560 if (linkInfoC != null)
561 {
562 linkInfoC.constraintType = (ConstraintType)requestedType;
563 ret = (object)true;
564 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,link={1},type={2}",
565 linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
566 }
567 else
568 {
569 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,linkInfoNotConstraint,childID={1}", LinksetRoot.LocalID, child.LocalID);
570 }
571 }
572 else
573 {
574 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,noLinkInfoForChild,childID={1}", LinksetRoot.LocalID, child.LocalID);
575 }
576 // Cause the whole linkset to be rebuilt in post-taint time.
577 Refresh(child);
578 });
579 }
580 else
581 {
582 DetailLog("{0},BSLinksetConstraint.SetLinkType,childNotBSPrimLinkable", LinksetRoot.LocalID);
583 }
584 }
585 else
586 {
587 DetailLog("{0},BSLinksetConstraint.SetLinkType,illegalRequestedType,reqested={1},spring={2}",
588 LinksetRoot.LocalID, requestedType, ((int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE));
589 }
590 }
591 break;
592 // pParams = [ BSPhysObject root, BSPhysObject child ]
593 case ExtendedPhysics.PhysFunctGetLinkType:
594 if (pParams.Length > 0)
595 {
596 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
597 if (child != null)
598 {
599 BSLinkInfo linkInfo = null;
600 if (TryGetLinkInfo(child, out linkInfo))
601 {
602 BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
603 if (linkInfoC != null)
604 {
605 ret = (object)(int)linkInfoC.constraintType;
606 DetailLog("{0},BSLinksetConstraint.GetLinkType,link={1},type={2}",
607 linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
608
609 }
610 }
611 }
612 }
613 break;
614 // pParams = [ BSPhysObject root, BSPhysObject child, int op, object opParams, int op, object opParams, ... ]
615 case ExtendedPhysics.PhysFunctChangeLinkParams:
616 // There should be two parameters: the childActor and a list of parameters to set
617 if (pParams.Length > 2)
618 {
619 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
620 BSLinkInfo baseLinkInfo = null;
621 if (TryGetLinkInfo(child, out baseLinkInfo))
622 {
623 BSLinkInfoConstraint linkInfo = baseLinkInfo as BSLinkInfoConstraint;
624 if (linkInfo != null)
625 {
626 int valueInt;
627 float valueFloat;
628 bool valueBool;
629 OMV.Vector3 valueVector;
630 OMV.Vector3 valueVector2;
631 OMV.Quaternion valueQuaternion;
632 int axisLow, axisHigh;
633
634 int opIndex = 2;
635 while (opIndex < pParams.Length)
636 {
637 int thisOp = 0;
638 string errMsg = "";
639 try
640 {
641 thisOp = (int)pParams[opIndex];
642 DetailLog("{0},BSLinksetConstraint.ChangeLinkParams2,op={1},val={2}",
643 linkInfo.member.LocalID, thisOp, pParams[opIndex + 1]);
644 switch (thisOp)
645 {
646 case ExtendedPhysics.PHYS_PARAM_LINK_TYPE:
647 valueInt = (int)pParams[opIndex + 1];
648 ConstraintType valueType = (ConstraintType)valueInt;
649 if (valueType == ConstraintType.FIXED_CONSTRAINT_TYPE
650 || valueType == ConstraintType.D6_CONSTRAINT_TYPE
651 || valueType == ConstraintType.D6_SPRING_CONSTRAINT_TYPE
652 || valueType == ConstraintType.HINGE_CONSTRAINT_TYPE
653 || valueType == ConstraintType.CONETWIST_CONSTRAINT_TYPE
654 || valueType == ConstraintType.SLIDER_CONSTRAINT_TYPE)
655 {
656 linkInfo.constraintType = valueType;
657 }
658 opIndex += 2;
659 break;
660 case ExtendedPhysics.PHYS_PARAM_FRAMEINA_LOC:
661 errMsg = "PHYS_PARAM_FRAMEINA_LOC takes one parameter of type vector";
662 valueVector = (OMV.Vector3)pParams[opIndex + 1];
663 linkInfo.frameInAloc = valueVector;
664 opIndex += 2;
665 break;
666 case ExtendedPhysics.PHYS_PARAM_FRAMEINA_ROT:
667 errMsg = "PHYS_PARAM_FRAMEINA_ROT takes one parameter of type rotation";
668 valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
669 linkInfo.frameInArot = valueQuaternion;
670 opIndex += 2;
671 break;
672 case ExtendedPhysics.PHYS_PARAM_FRAMEINB_LOC:
673 errMsg = "PHYS_PARAM_FRAMEINB_LOC takes one parameter of type vector";
674 valueVector = (OMV.Vector3)pParams[opIndex + 1];
675 linkInfo.frameInBloc = valueVector;
676 opIndex += 2;
677 break;
678 case ExtendedPhysics.PHYS_PARAM_FRAMEINB_ROT:
679 errMsg = "PHYS_PARAM_FRAMEINB_ROT takes one parameter of type rotation";
680 valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
681 linkInfo.frameInBrot = valueQuaternion;
682 opIndex += 2;
683 break;
684 case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_LOW:
685 errMsg = "PHYS_PARAM_LINEAR_LIMIT_LOW takes one parameter of type vector";
686 valueVector = (OMV.Vector3)pParams[opIndex + 1];
687 linkInfo.linearLimitLow = valueVector;
688 opIndex += 2;
689 break;
690 case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_HIGH:
691 errMsg = "PHYS_PARAM_LINEAR_LIMIT_HIGH takes one parameter of type vector";
692 valueVector = (OMV.Vector3)pParams[opIndex + 1];
693 linkInfo.linearLimitHigh = valueVector;
694 opIndex += 2;
695 break;
696 case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_LOW:
697 errMsg = "PHYS_PARAM_ANGULAR_LIMIT_LOW takes one parameter of type vector";
698 valueVector = (OMV.Vector3)pParams[opIndex + 1];
699 linkInfo.angularLimitLow = valueVector;
700 opIndex += 2;
701 break;
702 case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_HIGH:
703 errMsg = "PHYS_PARAM_ANGULAR_LIMIT_HIGH takes one parameter of type vector";
704 valueVector = (OMV.Vector3)pParams[opIndex + 1];
705 linkInfo.angularLimitHigh = valueVector;
706 opIndex += 2;
707 break;
708 case ExtendedPhysics.PHYS_PARAM_USE_FRAME_OFFSET:
709 errMsg = "PHYS_PARAM_USE_FRAME_OFFSET takes one parameter of type integer (bool)";
710 valueBool = ((int)pParams[opIndex + 1]) != 0;
711 linkInfo.useFrameOffset = valueBool;
712 opIndex += 2;
713 break;
714 case ExtendedPhysics.PHYS_PARAM_ENABLE_TRANSMOTOR:
715 errMsg = "PHYS_PARAM_ENABLE_TRANSMOTOR takes one parameter of type integer (bool)";
716 valueBool = ((int)pParams[opIndex + 1]) != 0;
717 linkInfo.enableTransMotor = valueBool;
718 opIndex += 2;
719 break;
720 case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXVEL:
721 errMsg = "PHYS_PARAM_TRANSMOTOR_MAXVEL takes one parameter of type float";
722 valueFloat = (float)pParams[opIndex + 1];
723 linkInfo.transMotorMaxVel = valueFloat;
724 opIndex += 2;
725 break;
726 case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXFORCE:
727 errMsg = "PHYS_PARAM_TRANSMOTOR_MAXFORCE takes one parameter of type float";
728 valueFloat = (float)pParams[opIndex + 1];
729 linkInfo.transMotorMaxForce = valueFloat;
730 opIndex += 2;
731 break;
732 case ExtendedPhysics.PHYS_PARAM_CFM:
733 errMsg = "PHYS_PARAM_CFM takes one parameter of type float";
734 valueFloat = (float)pParams[opIndex + 1];
735 linkInfo.cfm = valueFloat;
736 opIndex += 2;
737 break;
738 case ExtendedPhysics.PHYS_PARAM_ERP:
739 errMsg = "PHYS_PARAM_ERP takes one parameter of type float";
740 valueFloat = (float)pParams[opIndex + 1];
741 linkInfo.erp = valueFloat;
742 opIndex += 2;
743 break;
744 case ExtendedPhysics.PHYS_PARAM_SOLVER_ITERATIONS:
745 errMsg = "PHYS_PARAM_SOLVER_ITERATIONS takes one parameter of type float";
746 valueFloat = (float)pParams[opIndex + 1];
747 linkInfo.solverIterations = valueFloat;
748 opIndex += 2;
749 break;
750 case ExtendedPhysics.PHYS_PARAM_SPRING_AXIS_ENABLE:
751 errMsg = "PHYS_PARAM_SPRING_AXIS_ENABLE takes two parameters of types integer and integer (bool)";
752 valueInt = (int)pParams[opIndex + 1];
753 valueBool = ((int)pParams[opIndex + 2]) != 0;
754 GetAxisRange(valueInt, out axisLow, out axisHigh);
755 for (int ii = axisLow; ii <= axisHigh; ii++)
756 linkInfo.springAxisEnable[ii] = valueBool;
757 opIndex += 3;
758 break;
759 case ExtendedPhysics.PHYS_PARAM_SPRING_DAMPING:
760 errMsg = "PHYS_PARAM_SPRING_DAMPING takes two parameters of types integer and float";
761 valueInt = (int)pParams[opIndex + 1];
762 valueFloat = (float)pParams[opIndex + 2];
763 GetAxisRange(valueInt, out axisLow, out axisHigh);
764 for (int ii = axisLow; ii <= axisHigh; ii++)
765 linkInfo.springDamping[ii] = valueFloat;
766 opIndex += 3;
767 break;
768 case ExtendedPhysics.PHYS_PARAM_SPRING_STIFFNESS:
769 errMsg = "PHYS_PARAM_SPRING_STIFFNESS takes two parameters of types integer and float";
770 valueInt = (int)pParams[opIndex + 1];
771 valueFloat = (float)pParams[opIndex + 2];
772 GetAxisRange(valueInt, out axisLow, out axisHigh);
773 for (int ii = axisLow; ii <= axisHigh; ii++)
774 linkInfo.springStiffness[ii] = valueFloat;
775 opIndex += 3;
776 break;
777 case ExtendedPhysics.PHYS_PARAM_SPRING_EQUILIBRIUM_POINT:
778 errMsg = "PHYS_PARAM_SPRING_EQUILIBRIUM_POINT takes two parameters of type vector";
779 valueVector = (OMV.Vector3)pParams[opIndex + 1];
780 valueVector2 = (OMV.Vector3)pParams[opIndex + 2];
781 linkInfo.springLinearEquilibriumPoint = valueVector;
782 linkInfo.springAngularEquilibriumPoint = valueVector2;
783 opIndex += 3;
784 break;
785 case ExtendedPhysics.PHYS_PARAM_USE_LINEAR_FRAMEA:
786 errMsg = "PHYS_PARAM_USE_LINEAR_FRAMEA takes one parameter of type integer (bool)";
787 valueBool = ((int)pParams[opIndex + 1]) != 0;
788 linkInfo.useLinearReferenceFrameA = valueBool;
789 opIndex += 2;
790 break;
791 default:
792 break;
793 }
794 }
795 catch (InvalidCastException e)
796 {
797 m_physicsScene.Logger.WarnFormat("{0} value of wrong type in physSetLinksetParams: {1}, err={2}",
798 LogHeader, errMsg, e);
799 }
800 catch (Exception e)
801 {
802 m_physicsScene.Logger.WarnFormat("{0} bad parameters in physSetLinksetParams: {1}", LogHeader, e);
803 }
804 }
805 }
806 // Something changed so a rebuild is in order
807 Refresh(child);
808 }
809 }
810 break;
811 default:
812 ret = base.Extension(pFunct, pParams);
813 break;
814 }
815 return ret;
816 }
817
818 // Bullet constraints keep some limit parameters for each linear and angular axis.
819 // Setting same is easier if there is an easy way to see all or types.
820 // This routine returns the array limits for the set of axis.
821 private void GetAxisRange(int rangeSpec, out int low, out int high)
822 {
823 switch (rangeSpec)
824 {
825 case ExtendedPhysics.PHYS_AXIS_LINEAR_ALL:
826 low = 0;
827 high = 2;
828 break;
829 case ExtendedPhysics.PHYS_AXIS_ANGULAR_ALL:
830 low = 3;
831 high = 5;
832 break;
833 case ExtendedPhysics.PHYS_AXIS_ALL:
834 low = 0;
835 high = 5;
836 break;
837 default:
838 low = high = rangeSpec;
839 break;
840 }
841 return;
302 } 842 }
843 #endregion // Extension
844
303} 845}
304} 846}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index 9501e2d..7693195 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -65,13 +65,11 @@ public abstract class BSMotor
65} 65}
66 66
67// Motor which moves CurrentValue to TargetValue over TimeScale seconds. 67// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
68// The TargetValue decays in TargetValueDecayTimeScale and 68// The TargetValue decays in TargetValueDecayTimeScale.
69// the CurrentValue will be held back by FrictionTimeScale.
70// This motor will "zero itself" over time in that the targetValue will 69// This motor will "zero itself" over time in that the targetValue will
71// decay to zero and the currentValue will follow it to that zero. 70// decay to zero and the currentValue will follow it to that zero.
72// The overall effect is for the returned correction value to go from large 71// The overall effect is for the returned correction value to go from large
73// values (the total difference between current and target minus friction) 72// values to small and eventually zero values.
74// to small and eventually zero values.
75// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay. 73// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay.
76 74
77// For instance, if something is moving at speed X and the desired speed is Y, 75// For instance, if something is moving at speed X and the desired speed is Y,
@@ -88,7 +86,6 @@ public class BSVMotor : BSMotor
88 86
89 public virtual float TimeScale { get; set; } 87 public virtual float TimeScale { get; set; }
90 public virtual float TargetValueDecayTimeScale { get; set; } 88 public virtual float TargetValueDecayTimeScale { get; set; }
91 public virtual Vector3 FrictionTimescale { get; set; }
92 public virtual float Efficiency { get; set; } 89 public virtual float Efficiency { get; set; }
93 90
94 public virtual float ErrorZeroThreshold { get; set; } 91 public virtual float ErrorZeroThreshold { get; set; }
@@ -102,7 +99,7 @@ public class BSVMotor : BSMotor
102 return ErrorIsZero(LastError); 99 return ErrorIsZero(LastError);
103 } 100 }
104 public virtual bool ErrorIsZero(Vector3 err) 101 public virtual bool ErrorIsZero(Vector3 err)
105 { 102 {
106 return (err == Vector3.Zero || err.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)); 103 return (err == Vector3.Zero || err.ApproxEquals(Vector3.Zero, ErrorZeroThreshold));
107 } 104 }
108 105
@@ -111,16 +108,14 @@ public class BSVMotor : BSMotor
111 { 108 {
112 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; 109 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
113 Efficiency = 1f; 110 Efficiency = 1f;
114 FrictionTimescale = BSMotor.InfiniteVector;
115 CurrentValue = TargetValue = Vector3.Zero; 111 CurrentValue = TargetValue = Vector3.Zero;
116 ErrorZeroThreshold = 0.001f; 112 ErrorZeroThreshold = 0.001f;
117 } 113 }
118 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) 114 public BSVMotor(string useName, float timeScale, float decayTimeScale, float efficiency)
119 : this(useName) 115 : this(useName)
120 { 116 {
121 TimeScale = timeScale; 117 TimeScale = timeScale;
122 TargetValueDecayTimeScale = decayTimeScale; 118 TargetValueDecayTimeScale = decayTimeScale;
123 FrictionTimescale = frictionTimeScale;
124 Efficiency = efficiency; 119 Efficiency = efficiency;
125 CurrentValue = TargetValue = Vector3.Zero; 120 CurrentValue = TargetValue = Vector3.Zero;
126 } 121 }
@@ -149,7 +144,6 @@ public class BSVMotor : BSMotor
149 144
150 Vector3 correction = Vector3.Zero; 145 Vector3 correction = Vector3.Zero;
151 Vector3 error = TargetValue - CurrentValue; 146 Vector3 error = TargetValue - CurrentValue;
152 LastError = error;
153 if (!ErrorIsZero(error)) 147 if (!ErrorIsZero(error))
154 { 148 {
155 correction = StepError(timeStep, error); 149 correction = StepError(timeStep, error);
@@ -165,26 +159,11 @@ public class BSVMotor : BSMotor
165 TargetValue *= (1f - decayFactor); 159 TargetValue *= (1f - decayFactor);
166 } 160 }
167 161
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}", 162 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
182 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, 163 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
183 timeStep, error, correction); 164 timeStep, error, correction);
184 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}", 165 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},tgt={4},curr={5}",
185 BSScene.DetailLogZero, UseName, 166 BSScene.DetailLogZero, UseName, TargetValueDecayTimeScale, decayFactor, TargetValue, CurrentValue);
186 TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
187 TargetValue, CurrentValue);
188 } 167 }
189 else 168 else
190 { 169 {
@@ -199,6 +178,7 @@ public class BSVMotor : BSMotor
199 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},currTgt={4},currCurr={5}", 178 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},currTgt={4},currCurr={5}",
200 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, TargetValue, CurrentValue); 179 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, TargetValue, CurrentValue);
201 } 180 }
181 LastError = error;
202 182
203 return correction; 183 return correction;
204 } 184 }
@@ -208,6 +188,8 @@ public class BSVMotor : BSMotor
208 CurrentValue = current; 188 CurrentValue = current;
209 return Step(timeStep); 189 return Step(timeStep);
210 } 190 }
191 // Given and error, computer a correction for this step.
192 // Simple scaling of the error by the timestep.
211 public virtual Vector3 StepError(float timeStep, Vector3 error) 193 public virtual Vector3 StepError(float timeStep, Vector3 error)
212 { 194 {
213 if (!Enabled) return Vector3.Zero; 195 if (!Enabled) return Vector3.Zero;
@@ -235,27 +217,27 @@ public class BSVMotor : BSMotor
235 // maximum number of outputs to generate. 217 // maximum number of outputs to generate.
236 int maxOutput = 50; 218 int maxOutput = 50;
237 MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName); 219 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}", 220 MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},eff={4},curr={5},tgt={6}",
239 BSScene.DetailLogZero, UseName, 221 BSScene.DetailLogZero, UseName,
240 TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency, 222 TimeScale, TargetValueDecayTimeScale, Efficiency,
241 CurrentValue, TargetValue); 223 CurrentValue, TargetValue);
242 224
243 LastError = BSMotor.InfiniteVector; 225 LastError = BSMotor.InfiniteVector;
244 while (maxOutput-- > 0 && !LastError.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) 226 while (maxOutput-- > 0 && !ErrorIsZero())
245 { 227 {
246 Vector3 lastStep = Step(timeStep); 228 Vector3 lastStep = Step(timeStep);
247 MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}", 229 MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}",
248 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep); 230 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep);
249 } 231 }
250 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName); 232 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName);
251 233
252 234
253 } 235 }
254 236
255 public override string ToString() 237 public override string ToString()
256 { 238 {
257 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>", 239 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4}>",
258 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale); 240 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale);
259 } 241 }
260} 242}
261 243
@@ -265,7 +247,6 @@ public class BSFMotor : BSMotor
265{ 247{
266 public virtual float TimeScale { get; set; } 248 public virtual float TimeScale { get; set; }
267 public virtual float TargetValueDecayTimeScale { get; set; } 249 public virtual float TargetValueDecayTimeScale { get; set; }
268 public virtual float FrictionTimescale { get; set; }
269 public virtual float Efficiency { get; set; } 250 public virtual float Efficiency { get; set; }
270 251
271 public virtual float ErrorZeroThreshold { get; set; } 252 public virtual float ErrorZeroThreshold { get; set; }
@@ -279,16 +260,15 @@ public class BSFMotor : BSMotor
279 return ErrorIsZero(LastError); 260 return ErrorIsZero(LastError);
280 } 261 }
281 public virtual bool ErrorIsZero(float err) 262 public virtual bool ErrorIsZero(float err)
282 { 263 {
283 return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold); 264 return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold);
284 } 265 }
285 266
286 public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency) 267 public BSFMotor(string useName, float timeScale, float decayTimescale, float efficiency)
287 : base(useName) 268 : base(useName)
288 { 269 {
289 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; 270 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
290 Efficiency = 1f; 271 Efficiency = 1f;
291 FrictionTimescale = BSMotor.Infinite;
292 CurrentValue = TargetValue = 0f; 272 CurrentValue = TargetValue = 0f;
293 ErrorZeroThreshold = 0.01f; 273 ErrorZeroThreshold = 0.01f;
294 } 274 }
@@ -315,7 +295,6 @@ public class BSFMotor : BSMotor
315 295
316 float correction = 0f; 296 float correction = 0f;
317 float error = TargetValue - CurrentValue; 297 float error = TargetValue - CurrentValue;
318 LastError = error;
319 if (!ErrorIsZero(error)) 298 if (!ErrorIsZero(error))
320 { 299 {
321 correction = StepError(timeStep, error); 300 correction = StepError(timeStep, error);
@@ -331,24 +310,11 @@ public class BSFMotor : BSMotor
331 TargetValue *= (1f - decayFactor); 310 TargetValue *= (1f - decayFactor);
332 } 311 }
333 312
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}", 313 MDetailLog("{0}, BSFMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
346 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, 314 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
347 timeStep, error, correction); 315 timeStep, error, correction);
348 MDetailLog("{0}, BSFMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}", 316 MDetailLog("{0}, BSFMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},tgt={4},curr={5}",
349 BSScene.DetailLogZero, UseName, 317 BSScene.DetailLogZero, UseName, TargetValueDecayTimeScale, decayFactor, TargetValue, CurrentValue);
350 TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
351 TargetValue, CurrentValue);
352 } 318 }
353 else 319 else
354 { 320 {
@@ -363,6 +329,7 @@ public class BSFMotor : BSMotor
363 MDetailLog("{0}, BSFMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}", 329 MDetailLog("{0}, BSFMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}",
364 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue); 330 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue);
365 } 331 }
332 LastError = error;
366 333
367 return CurrentValue; 334 return CurrentValue;
368 } 335 }
@@ -390,15 +357,15 @@ public class BSFMotor : BSMotor
390 357
391 public override string ToString() 358 public override string ToString()
392 { 359 {
393 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>", 360 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4}>",
394 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale); 361 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale);
395 } 362 }
396 363
397} 364}
398 365
399// ============================================================================ 366// ============================================================================
400// ============================================================================ 367// ============================================================================
401// Proportional, Integral, Derivitive Motor 368// Proportional, Integral, Derivitive ("PID") Motor
402// Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors. 369// Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors.
403public class BSPIDVMotor : BSVMotor 370public class BSPIDVMotor : BSVMotor
404{ 371{
@@ -410,7 +377,6 @@ public class BSPIDVMotor : BSVMotor
410 // The factors are vectors for the three dimensions. This is the proportional of each 377 // 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 378 // 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. 379 // is sometimes easier to manipulate the factors and their mix separately.
413 // to
414 public Vector3 FactorMix; 380 public Vector3 FactorMix;
415 381
416 // Arbritrary factor range. 382 // Arbritrary factor range.
@@ -448,14 +414,14 @@ public class BSPIDVMotor : BSVMotor
448 // If efficiency is high (1f), use a factor value that moves the error value to zero with little overshoot. 414 // 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. 415 // If efficiency is low (0f), use a factor value that overcorrects.
450 // TODO: might want to vary contribution of different factor depending on efficiency. 416 // TODO: might want to vary contribution of different factor depending on efficiency.
451 float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f; 417 // float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f;
452 // float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow; 418 float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow;
453 419
454 proportionFactor = new Vector3(factor, factor, factor); 420 proportionFactor = new Vector3(factor, factor, factor);
455 integralFactor = new Vector3(factor, factor, factor); 421 integralFactor = new Vector3(factor, factor, factor);
456 derivFactor = new Vector3(factor, factor, factor); 422 derivFactor = new Vector3(factor, factor, factor);
457 423
458 MDetailLog("{0},BSPIDVMotor.setEfficiency,eff={1},factor={2}", BSScene.DetailLogZero, Efficiency, factor); 424 MDetailLog("{0}, BSPIDVMotor.setEfficiency,eff={1},factor={2}", BSScene.DetailLogZero, Efficiency, factor);
459 } 425 }
460 } 426 }
461 427
@@ -469,16 +435,15 @@ public class BSPIDVMotor : BSVMotor
469 435
470 // A simple derivitive is the rate of change from the last error. 436 // A simple derivitive is the rate of change from the last error.
471 Vector3 derivitive = (error - LastError) * timeStep; 437 Vector3 derivitive = (error - LastError) * timeStep;
472 LastError = error;
473 438
474 // Correction = (proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError) 439 // Correction = (proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError)
475 Vector3 ret = error * timeStep * proportionFactor * FactorMix.X 440 Vector3 ret = error / TimeScale * timeStep * proportionFactor * FactorMix.X
476 + RunningIntegration * integralFactor * FactorMix.Y 441 + RunningIntegration / TimeScale * integralFactor * FactorMix.Y
477 + derivitive * derivFactor * FactorMix.Z 442 + derivitive / TimeScale * derivFactor * FactorMix.Z
478 ; 443 ;
479 444
480 MDetailLog("{0},BSPIDVMotor.step,ts={1},err={2},runnInt={3},deriv={4},ret={5}", 445 MDetailLog("{0}, BSPIDVMotor.step,ts={1},err={2},lerr={3},runnInt={4},deriv={5},ret={6}",
481 BSScene.DetailLogZero, timeStep, error, RunningIntegration, derivitive, ret); 446 BSScene.DetailLogZero, timeStep, error, LastError, RunningIntegration, derivitive, ret);
482 447
483 return ret; 448 return ret;
484 } 449 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 385ed9e..834228e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection;
29using System.Text; 30using System.Text;
30 31
31using OpenSim.Region.Physics.Manager; 32using OpenSim.Region.Physics.Manager;
@@ -37,7 +38,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
37{ 38{
38public static class BSParam 39public static class BSParam
39{ 40{
40 private static string LogHeader = "[BULLETSIM PARAMETERS]"; 41 private static string LogHeader = "[BULLETSIM PARAMETERS]";
41 42
42 // Tuning notes: 43 // Tuning notes:
43 // From: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6575 44 // From: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6575
@@ -51,7 +52,10 @@ public static class BSParam
51 // This is separate/independent from the collision margin. The collision margin increases the object a bit 52 // This is separate/independent from the collision margin. The collision margin increases the object a bit
52 // to improve collision detection performance and accuracy. 53 // to improve collision detection performance and accuracy.
53 // =================== 54 // ===================
54 // From: 55 // From:
56
57 public static bool UseSeparatePhysicsThread { get; private set; }
58 public static float PhysicsTimeStep { get; private set; }
55 59
56 // Level of Detail values kept as float because that's what the Meshmerizer wants 60 // Level of Detail values kept as float because that's what the Meshmerizer wants
57 public static float MeshLOD { get; private set; } 61 public static float MeshLOD { get; private set; }
@@ -86,8 +90,12 @@ public static class BSParam
86 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes 90 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
87 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects 91 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
88 public static bool ShouldRemoveZeroWidthTriangles { get; private set; } 92 public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
93 public static bool ShouldUseBulletHACD { get; set; }
94 public static bool ShouldUseSingleConvexHullForPrims { get; set; }
95 public static bool ShouldUseGImpactShapeForPrims { get; set; }
96 public static bool ShouldUseAssetHulls { get; set; }
89 97
90 public static float TerrainImplementation { get; private set; } 98 public static float TerrainImplementation { get; set; }
91 public static int TerrainMeshMagnification { get; private set; } 99 public static int TerrainMeshMagnification { get; private set; }
92 public static float TerrainFriction { get; private set; } 100 public static float TerrainFriction { get; private set; }
93 public static float TerrainHitFraction { get; private set; } 101 public static float TerrainHitFraction { get; private set; }
@@ -112,6 +120,7 @@ public static class BSParam
112 public static float NumberOfSolverIterations { get; private set; } 120 public static float NumberOfSolverIterations { get; private set; }
113 public static bool UseSingleSidedMeshes { get; private set; } 121 public static bool UseSingleSidedMeshes { get; private set; }
114 public static float GlobalContactBreakingThreshold { get; private set; } 122 public static float GlobalContactBreakingThreshold { get; private set; }
123 public static float PhysicsUnmanLoggingFrames { get; private set; }
115 124
116 // Avatar parameters 125 // Avatar parameters
117 public static float AvatarFriction { get; private set; } 126 public static float AvatarFriction { get; private set; }
@@ -122,11 +131,18 @@ public static class BSParam
122 public static float AvatarCapsuleWidth { get; private set; } 131 public static float AvatarCapsuleWidth { get; private set; }
123 public static float AvatarCapsuleDepth { get; private set; } 132 public static float AvatarCapsuleDepth { get; private set; }
124 public static float AvatarCapsuleHeight { get; private set; } 133 public static float AvatarCapsuleHeight { get; private set; }
134 public static float AvatarHeightLowFudge { get; private set; }
135 public static float AvatarHeightMidFudge { get; private set; }
136 public static float AvatarHeightHighFudge { get; private set; }
125 public static float AvatarContactProcessingThreshold { get; private set; } 137 public static float AvatarContactProcessingThreshold { get; private set; }
138 public static float AvatarStopZeroThreshold { get; private set; }
139 public static int AvatarJumpFrames { get; private set; }
126 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } 140 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; }
127 public static float AvatarStepHeight { get; private set; } 141 public static float AvatarStepHeight { get; private set; }
128 public static float AvatarStepApproachFactor { get; private set; } 142 public static float AvatarStepApproachFactor { get; private set; }
129 public static float AvatarStepForceFactor { get; private set; } 143 public static float AvatarStepForceFactor { get; private set; }
144 public static float AvatarStepUpCorrectionFactor { get; private set; }
145 public static int AvatarStepSmoothingSteps { get; private set; }
130 146
131 // Vehicle parameters 147 // Vehicle parameters
132 public static float VehicleMaxLinearVelocity { get; private set; } 148 public static float VehicleMaxLinearVelocity { get; private set; }
@@ -138,9 +154,15 @@ public static class BSParam
138 public static float VehicleRestitution { get; private set; } 154 public static float VehicleRestitution { get; private set; }
139 public static Vector3 VehicleLinearFactor { get; private set; } 155 public static Vector3 VehicleLinearFactor { get; private set; }
140 public static Vector3 VehicleAngularFactor { get; private set; } 156 public static Vector3 VehicleAngularFactor { get; private set; }
157 public static Vector3 VehicleInertiaFactor { get; private set; }
141 public static float VehicleGroundGravityFudge { get; private set; } 158 public static float VehicleGroundGravityFudge { get; private set; }
142 public static float VehicleAngularBankingTimescaleFudge { get; private set; } 159 public static float VehicleAngularBankingTimescaleFudge { get; private set; }
143 public static bool VehicleDebuggingEnabled { get; private set; } 160 public static bool VehicleEnableLinearDeflection { get; private set; }
161 public static bool VehicleLinearDeflectionNotCollidingNoZ { get; private set; }
162 public static bool VehicleEnableAngularVerticalAttraction { get; private set; }
163 public static int VehicleAngularVerticalAttractionAlgorithm { get; private set; }
164 public static bool VehicleEnableAngularDeflection { get; private set; }
165 public static bool VehicleEnableAngularBanking { get; private set; }
144 166
145 // Convex Hulls 167 // Convex Hulls
146 public static int CSHullMaxDepthSplit { get; private set; } 168 public static int CSHullMaxDepthSplit { get; private set; }
@@ -149,9 +171,19 @@ public static class BSParam
149 public static float CSHullVolumeConservationThresholdPercent { get; private set; } 171 public static float CSHullVolumeConservationThresholdPercent { get; private set; }
150 public static int CSHullMaxVertices { get; private set; } 172 public static int CSHullMaxVertices { get; private set; }
151 public static float CSHullMaxSkinWidth { get; private set; } 173 public static float CSHullMaxSkinWidth { get; private set; }
174 public static float BHullMaxVerticesPerHull { get; private set; } // 100
175 public static float BHullMinClusters { get; private set; } // 2
176 public static float BHullCompacityWeight { get; private set; } // 0.1
177 public static float BHullVolumeWeight { get; private set; } // 0.0
178 public static float BHullConcavity { get; private set; } // 100
179 public static bool BHullAddExtraDistPoints { get; private set; } // false
180 public static bool BHullAddNeighboursDistPoints { get; private set; } // false
181 public static bool BHullAddFacesPoints { get; private set; } // false
182 public static bool BHullShouldAdjustCollisionMargin { get; private set; } // false
152 183
153 // Linkset implementation parameters 184 // Linkset implementation parameters
154 public static float LinksetImplementation { get; private set; } 185 public static float LinksetImplementation { get; private set; }
186 public static bool LinksetOffsetCenterOfMass { get; private set; }
155 public static bool LinkConstraintUseFrameOffset { get; private set; } 187 public static bool LinkConstraintUseFrameOffset { get; private set; }
156 public static bool LinkConstraintEnableTransMotor { get; private set; } 188 public static bool LinkConstraintEnableTransMotor { get; private set; }
157 public static float LinkConstraintTransMotorMaxVel { get; private set; } 189 public static float LinkConstraintTransMotorMaxVel { get; private set; }
@@ -223,16 +255,41 @@ public static class BSParam
223 getter = pGetter; 255 getter = pGetter;
224 objectSet = pObjSetter; 256 objectSet = pObjSetter;
225 } 257 }
226 /* Wish I could simplify using this definition but CLR doesn't store references so closure around delegates of references won't work 258 // Simple parameter variable where property name is the same as the INI file name
227 public ParameterDefn(string pName, string pDesc, T pDefault, ref T loc) 259 // and the value is only a simple get and set.
260 public ParameterDefn(string pName, string pDesc, T pDefault)
228 : base(pName, pDesc) 261 : base(pName, pDesc)
229 { 262 {
230 defaultValue = pDefault; 263 defaultValue = pDefault;
231 setter = (s, v) => { loc = v; }; 264 setter = (s, v) => { SetValueByName(s, name, v); };
232 getter = (s) => { return loc; }; 265 getter = (s) => { return GetValueByName(s, name); };
233 objectSet = null; 266 objectSet = null;
234 } 267 }
235 */ 268 // Use reflection to find the property named 'pName' in BSParam and assign 'val' to same.
269 private void SetValueByName(BSScene s, string pName, T val)
270 {
271 PropertyInfo prop = typeof(BSParam).GetProperty(pName, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
272 if (prop == null)
273 {
274 // This should only be output when someone adds a new INI parameter and misspells the name.
275 s.Logger.ErrorFormat("{0} SetValueByName: did not find '{1}'. Verify specified property name is the same as the given INI parameters name.", LogHeader, pName);
276 }
277 else
278 {
279 prop.SetValue(null, val, null);
280 }
281 }
282 // Use reflection to find the property named 'pName' in BSParam and return the value in same.
283 private T GetValueByName(BSScene s, string pName)
284 {
285 PropertyInfo prop = typeof(BSParam).GetProperty(pName, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
286 if (prop == null)
287 {
288 // This should only be output when someone adds a new INI parameter and misspells the name.
289 s.Logger.ErrorFormat("{0} GetValueByName: did not find '{1}'. Verify specified property name is the same as the given INI parameter name.", LogHeader, pName);
290 }
291 return (T)prop.GetValue(null, null);
292 }
236 public override void AssignDefault(BSScene s) 293 public override void AssignDefault(BSScene s)
237 { 294 {
238 setter(s, defaultValue); 295 setter(s, defaultValue);
@@ -309,6 +366,11 @@ public static class BSParam
309 // v = value (appropriate type) 366 // v = value (appropriate type)
310 private static ParameterDefnBase[] ParameterDefinitions = 367 private static ParameterDefnBase[] ParameterDefinitions =
311 { 368 {
369 new ParameterDefn<bool>("UseSeparatePhysicsThread", "If 'true', the physics engine runs independent from the simulator heartbeat",
370 false ),
371 new ParameterDefn<float>("PhysicsTimeStep", "If separate thread, seconds to simulate each interval",
372 0.089f ),
373
312 new ParameterDefn<bool>("MeshSculptedPrim", "Whether to create meshes for sculpties", 374 new ParameterDefn<bool>("MeshSculptedPrim", "Whether to create meshes for sculpties",
313 true, 375 true,
314 (s) => { return ShouldMeshSculptedPrim; }, 376 (s) => { return ShouldMeshSculptedPrim; },
@@ -322,18 +384,20 @@ public static class BSParam
322 (s) => { return ShouldUseHullsForPhysicalObjects; }, 384 (s) => { return ShouldUseHullsForPhysicalObjects; },
323 (s,v) => { ShouldUseHullsForPhysicalObjects = v; } ), 385 (s,v) => { ShouldUseHullsForPhysicalObjects = v; } ),
324 new ParameterDefn<bool>("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes", 386 new ParameterDefn<bool>("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
325 true, 387 true ),
326 (s) => { return ShouldRemoveZeroWidthTriangles; }, 388 new ParameterDefn<bool>("ShouldUseBulletHACD", "If true, use the Bullet version of HACD",
327 (s,v) => { ShouldRemoveZeroWidthTriangles = v; } ), 389 false ),
390 new ParameterDefn<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims",
391 true ),
392 new ParameterDefn<bool>("ShouldUseGImpactShapeForPrims", "If true, use a GImpact shape for prims with cuts and twists",
393 false ),
394 new ParameterDefn<bool>("ShouldUseAssetHulls", "If true, use hull if specified in the mesh asset info",
395 true ),
328 396
329 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions", 397 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
330 5, 398 5 ),
331 (s) => { return CrossingFailuresBeforeOutOfBounds; },
332 (s,v) => { CrossingFailuresBeforeOutOfBounds = v; } ),
333 new ParameterDefn<float>("UpdateVelocityChangeThreshold", "Change in updated velocity required before reporting change to simulator", 399 new ParameterDefn<float>("UpdateVelocityChangeThreshold", "Change in updated velocity required before reporting change to simulator",
334 0.1f, 400 0.1f ),
335 (s) => { return UpdateVelocityChangeThreshold; },
336 (s,v) => { UpdateVelocityChangeThreshold = v; } ),
337 401
338 new ParameterDefn<float>("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 402 new ParameterDefn<float>("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
339 32f, 403 32f,
@@ -399,26 +463,22 @@ public static class BSParam
399 (s) => { return MaxAddForceMagnitude; }, 463 (s) => { return MaxAddForceMagnitude; },
400 (s,v) => { MaxAddForceMagnitude = v; MaxAddForceMagnitudeSquared = v * v; } ), 464 (s,v) => { MaxAddForceMagnitude = v; MaxAddForceMagnitudeSquared = v * v; } ),
401 // Density is passed around as 100kg/m3. This scales that to 1kg/m3. 465 // Density is passed around as 100kg/m3. This scales that to 1kg/m3.
466 // Reduce by power of 100 because Bullet doesn't seem to handle objects with large mass very well
402 new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)", 467 new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
403 0.01f, 468 0.01f ),
404 (s) => { return DensityScaleFactor; },
405 (s,v) => { DensityScaleFactor = v; } ),
406 469
407 new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing", 470 new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing",
408 2200f, 471 2200f ),
409 (s) => { return (float)PID_D; },
410 (s,v) => { PID_D = v; } ),
411 new ParameterDefn<float>("PID_P", "Parameteric factor for motion smoothing", 472 new ParameterDefn<float>("PID_P", "Parameteric factor for motion smoothing",
412 900f, 473 900f ),
413 (s) => { return (float)PID_P; },
414 (s,v) => { PID_P = v; } ),
415 474
416 new ParameterDefn<float>("DefaultFriction", "Friction factor used on new objects", 475 new ParameterDefn<float>("DefaultFriction", "Friction factor used on new objects",
417 0.2f, 476 0.2f,
418 (s) => { return DefaultFriction; }, 477 (s) => { return DefaultFriction; },
419 (s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ), 478 (s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
479 // For historical reasons, the viewer and simulator multiply the density by 100
420 new ParameterDefn<float>("DefaultDensity", "Density for new objects" , 480 new ParameterDefn<float>("DefaultDensity", "Density for new objects" ,
421 10.000006836f, // Aluminum g/cm3 481 1000.0006836f, // Aluminum g/cm3 * 100
422 (s) => { return DefaultDensity; }, 482 (s) => { return DefaultDensity; },
423 (s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ), 483 (s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
424 new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" , 484 new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" ,
@@ -478,86 +538,61 @@ public static class BSParam
478 (s,o) => { s.PE.SetContactProcessingThreshold(o.PhysBody, ContactProcessingThreshold); } ), 538 (s,o) => { s.PE.SetContactProcessingThreshold(o.PhysBody, ContactProcessingThreshold); } ),
479 539
480 new ParameterDefn<float>("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", 540 new ParameterDefn<float>("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
481 (float)BSTerrainPhys.TerrainImplementation.Mesh, 541 (float)BSTerrainPhys.TerrainImplementation.Mesh ),
482 (s) => { return TerrainImplementation; },
483 (s,v) => { TerrainImplementation = v; } ),
484 new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" , 542 new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" ,
485 2, 543 2 ),
486 (s) => { return TerrainMeshMagnification; },
487 (s,v) => { TerrainMeshMagnification = v; } ),
488 new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" , 544 new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
489 0.3f, 545 0.3f ),
490 (s) => { return TerrainFriction; },
491 (s,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
492 new ParameterDefn<float>("TerrainHitFraction", "Distance to measure hit collisions" , 546 new ParameterDefn<float>("TerrainHitFraction", "Distance to measure hit collisions" ,
493 0.8f, 547 0.8f ),
494 (s) => { return TerrainHitFraction; },
495 (s,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
496 new ParameterDefn<float>("TerrainRestitution", "Bouncyness" , 548 new ParameterDefn<float>("TerrainRestitution", "Bouncyness" ,
497 0f, 549 0f ),
498 (s) => { return TerrainRestitution; },
499 (s,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
500 new ParameterDefn<float>("TerrainContactProcessingThreshold", "Distance from terrain to stop processing collisions" , 550 new ParameterDefn<float>("TerrainContactProcessingThreshold", "Distance from terrain to stop processing collisions" ,
501 0.0f, 551 0.0f ),
502 (s) => { return TerrainContactProcessingThreshold; },
503 (s,v) => { TerrainContactProcessingThreshold = v; /* TODO: set on real terrain */ } ),
504 new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" , 552 new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" ,
505 0.08f, 553 0.08f ),
506 (s) => { return TerrainCollisionMargin; },
507 (s,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
508 554
509 new ParameterDefn<float>("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 555 new ParameterDefn<float>("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
510 0.2f, 556 0.2f ),
511 (s) => { return AvatarFriction; },
512 (s,v) => { AvatarFriction = v; } ),
513 new ParameterDefn<float>("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", 557 new ParameterDefn<float>("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
514 0.95f, 558 0.95f ),
515 (s) => { return AvatarStandingFriction; },
516 (s,v) => { AvatarStandingFriction = v; } ),
517 new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run", 559 new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
518 1.3f, 560 1.3f ),
519 (s) => { return AvatarAlwaysRunFactor; }, 561 // For historical reasons, density is reported * 100
520 (s,v) => { AvatarAlwaysRunFactor = v; } ), 562 new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation. Scaled times 100.",
521 new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 563 3500f) , // 3.5 * 100
522 3.5f,
523 (s) => { return AvatarDensity; },
524 (s,v) => { AvatarDensity = v; } ),
525 new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 564 new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
526 0f, 565 0f ),
527 (s) => { return AvatarRestitution; },
528 (s,v) => { AvatarRestitution = v; } ),
529 new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", 566 new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
530 0.6f, 567 0.6f ) ,
531 (s) => { return AvatarCapsuleWidth; },
532 (s,v) => { AvatarCapsuleWidth = v; } ),
533 new ParameterDefn<float>("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", 568 new ParameterDefn<float>("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
534 0.45f, 569 0.45f ),
535 (s) => { return AvatarCapsuleDepth; },
536 (s,v) => { AvatarCapsuleDepth = v; } ),
537 new ParameterDefn<float>("AvatarCapsuleHeight", "Default height of space around avatar", 570 new ParameterDefn<float>("AvatarCapsuleHeight", "Default height of space around avatar",
538 1.5f, 571 1.5f ),
539 (s) => { return AvatarCapsuleHeight; }, 572 new ParameterDefn<float>("AvatarHeightLowFudge", "A fudge factor to make small avatars stand on the ground",
540 (s,v) => { AvatarCapsuleHeight = v; } ), 573 -0.2f ),
574 new ParameterDefn<float>("AvatarHeightMidFudge", "A fudge distance to adjust average sized avatars to be standing on ground",
575 0.1f ),
576 new ParameterDefn<float>("AvatarHeightHighFudge", "A fudge factor to make tall avatars stand on the ground",
577 0.1f ),
541 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 578 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
542 0.1f, 579 0.1f ),
543 (s) => { return AvatarContactProcessingThreshold; }, 580 new ParameterDefn<float>("AvatarStopZeroThreshold", "Movement velocity below which avatar is assumed to be stopped",
544 (s,v) => { AvatarContactProcessingThreshold = v; } ), 581 0.1f ),
545 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", 582 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
546 1.0f, 583 1.0f ),
547 (s) => { return AvatarBelowGroundUpCorrectionMeters; }, 584 new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.",
548 (s,v) => { AvatarBelowGroundUpCorrectionMeters = v; } ), 585 4 ),
549 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", 586 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
550 0.3f, 587 0.6f ) ,
551 (s) => { return AvatarStepHeight; },
552 (s,v) => { AvatarStepHeight = v; } ),
553 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)", 588 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
554 0.6f, 589 0.6f ),
555 (s) => { return AvatarStepApproachFactor; },
556 (s,v) => { AvatarStepApproachFactor = v; } ),
557 new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step", 590 new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
558 2.0f, 591 1.0f ),
559 (s) => { return AvatarStepForceFactor; }, 592 new ParameterDefn<float>("AvatarStepUpCorrectionFactor", "Multiplied by height of step collision to create up movement at step",
560 (s,v) => { AvatarStepForceFactor = v; } ), 593 1.0f ),
594 new ParameterDefn<int>("AvatarStepSmoothingSteps", "Number of frames after a step collision that we continue walking up stairs",
595 2 ),
561 596
562 new ParameterDefn<float>("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle", 597 new ParameterDefn<float>("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
563 1000.0f, 598 1000.0f,
@@ -568,37 +603,33 @@ public static class BSParam
568 (s) => { return (float)VehicleMaxAngularVelocity; }, 603 (s) => { return (float)VehicleMaxAngularVelocity; },
569 (s,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ), 604 (s,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
570 new ParameterDefn<float>("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)", 605 new ParameterDefn<float>("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
571 0.0f, 606 0.0f ),
572 (s) => { return VehicleAngularDamping; },
573 (s,v) => { VehicleAngularDamping = v; } ),
574 new ParameterDefn<Vector3>("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (<0,0,0> to <1,1,1>)", 607 new ParameterDefn<Vector3>("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (<0,0,0> to <1,1,1>)",
575 new Vector3(1f, 1f, 1f), 608 new Vector3(1f, 1f, 1f) ),
576 (s) => { return VehicleLinearFactor; },
577 (s,v) => { VehicleLinearFactor = v; } ),
578 new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)", 609 new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)",
579 new Vector3(1f, 1f, 1f), 610 new Vector3(1f, 1f, 1f) ),
580 (s) => { return VehicleAngularFactor; }, 611 new ParameterDefn<Vector3>("VehicleInertiaFactor", "Fraction of physical inertia applied (<0,0,0> to <1,1,1>)",
581 (s,v) => { VehicleAngularFactor = v; } ), 612 new Vector3(1f, 1f, 1f) ),
582 new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)", 613 new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
583 0.0f, 614 0.0f ),
584 (s) => { return VehicleFriction; },
585 (s,v) => { VehicleFriction = v; } ),
586 new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)", 615 new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
587 0.0f, 616 0.0f ),
588 (s) => { return VehicleRestitution; },
589 (s,v) => { VehicleRestitution = v; } ),
590 new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)", 617 new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
591 0.2f, 618 0.2f ),
592 (s) => { return VehicleGroundGravityFudge; },
593 (s,v) => { VehicleGroundGravityFudge = v; } ),
594 new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.", 619 new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.",
595 60.0f, 620 60.0f ),
596 (s) => { return VehicleAngularBankingTimescaleFudge; }, 621 new ParameterDefn<bool>("VehicleEnableLinearDeflection", "Turn on/off vehicle linear deflection effect",
597 (s,v) => { VehicleAngularBankingTimescaleFudge = v; } ), 622 true ),
598 new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging", 623 new ParameterDefn<bool>("VehicleLinearDeflectionNotCollidingNoZ", "Turn on/off linear deflection Z effect on non-colliding vehicles",
599 false, 624 true ),
600 (s) => { return VehicleDebuggingEnabled; }, 625 new ParameterDefn<bool>("VehicleEnableAngularVerticalAttraction", "Turn on/off vehicle angular vertical attraction effect",
601 (s,v) => { VehicleDebuggingEnabled = v; } ), 626 true ),
627 new ParameterDefn<int>("VehicleAngularVerticalAttractionAlgorithm", "Select vertical attraction algo. You need to look at the source.",
628 0 ),
629 new ParameterDefn<bool>("VehicleEnableAngularDeflection", "Turn on/off vehicle angular deflection effect",
630 true ),
631 new ParameterDefn<bool>("VehicleEnableAngularBanking", "Turn on/off vehicle angular banking effect",
632 true ),
602 633
603 new ParameterDefn<float>("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 634 new ParameterDefn<float>("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
604 0f, 635 0f,
@@ -611,7 +642,7 @@ public static class BSParam
611 new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", 642 new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
612 false, 643 false,
613 (s) => { return ShouldDisableContactPoolDynamicAllocation; }, 644 (s) => { return ShouldDisableContactPoolDynamicAllocation; },
614 (s,v) => { ShouldDisableContactPoolDynamicAllocation = v; 645 (s,v) => { ShouldDisableContactPoolDynamicAllocation = v;
615 s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ), 646 s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ),
616 new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", 647 new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
617 false, 648 false,
@@ -641,64 +672,61 @@ public static class BSParam
641 0f, 672 0f,
642 (s) => { return GlobalContactBreakingThreshold; }, 673 (s) => { return GlobalContactBreakingThreshold; },
643 (s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ), 674 (s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
675 new ParameterDefn<float>("PhysicsUnmanLoggingFrames", "If non-zero, frames between output of detailed unmanaged physics statistics",
676 0f,
677 (s) => { return PhysicsUnmanLoggingFrames; },
678 (s,v) => { PhysicsUnmanLoggingFrames = v; s.UnmanagedParams[0].physicsLoggingFrames = v; } ),
644 679
645 new ParameterDefn<int>("CSHullMaxDepthSplit", "CS impl: max depth to split for hull. 1-10 but > 7 is iffy", 680 new ParameterDefn<int>("CSHullMaxDepthSplit", "CS impl: max depth to split for hull. 1-10 but > 7 is iffy",
646 7, 681 7 ),
647 (s) => { return CSHullMaxDepthSplit; },
648 (s,v) => { CSHullMaxDepthSplit = v; } ),
649 new ParameterDefn<int>("CSHullMaxDepthSplitForSimpleShapes", "CS impl: max depth setting for simple prim shapes", 682 new ParameterDefn<int>("CSHullMaxDepthSplitForSimpleShapes", "CS impl: max depth setting for simple prim shapes",
650 2, 683 2 ),
651 (s) => { return CSHullMaxDepthSplitForSimpleShapes; },
652 (s,v) => { CSHullMaxDepthSplitForSimpleShapes = v; } ),
653 new ParameterDefn<float>("CSHullConcavityThresholdPercent", "CS impl: concavity threshold percent (0-20)", 684 new ParameterDefn<float>("CSHullConcavityThresholdPercent", "CS impl: concavity threshold percent (0-20)",
654 5f, 685 5f ),
655 (s) => { return CSHullConcavityThresholdPercent; },
656 (s,v) => { CSHullConcavityThresholdPercent = v; } ),
657 new ParameterDefn<float>("CSHullVolumeConservationThresholdPercent", "percent volume conservation to collapse hulls (0-30)", 686 new ParameterDefn<float>("CSHullVolumeConservationThresholdPercent", "percent volume conservation to collapse hulls (0-30)",
658 5f, 687 5f ),
659 (s) => { return CSHullVolumeConservationThresholdPercent; },
660 (s,v) => { CSHullVolumeConservationThresholdPercent = v; } ),
661 new ParameterDefn<int>("CSHullMaxVertices", "CS impl: maximum number of vertices in output hulls. Keep < 50.", 688 new ParameterDefn<int>("CSHullMaxVertices", "CS impl: maximum number of vertices in output hulls. Keep < 50.",
662 32, 689 32 ),
663 (s) => { return CSHullMaxVertices; },
664 (s,v) => { CSHullMaxVertices = v; } ),
665 new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.", 690 new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
666 0, 691 0f ),
667 (s) => { return CSHullMaxSkinWidth; }, 692
668 (s,v) => { CSHullMaxSkinWidth = v; } ), 693 new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull",
694 200f ),
695 new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh",
696 10f ),
697 new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls",
698 20f ),
699 new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull",
700 0.1f ),
701 new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be",
702 10f ),
703 new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors",
704 true ),
705 new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls",
706 true ),
707 new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces",
708 true ),
709 new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
710 false ),
669 711
670 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", 712 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
671 (float)BSLinkset.LinksetImplementation.Compound, 713 (float)BSLinkset.LinksetImplementation.Compound ),
672 (s) => { return LinksetImplementation; }, 714 new ParameterDefn<bool>("LinksetOffsetCenterOfMass", "If 'true', compute linkset center-of-mass and offset linkset position to account for same",
673 (s,v) => { LinksetImplementation = v; } ), 715 true ),
674 new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", 716 new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
675 false, 717 false ),
676 (s) => { return LinkConstraintUseFrameOffset; },
677 (s,v) => { LinkConstraintUseFrameOffset = v; } ),
678 new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", 718 new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
679 true, 719 true ),
680 (s) => { return LinkConstraintEnableTransMotor; },
681 (s,v) => { LinkConstraintEnableTransMotor = v; } ),
682 new ParameterDefn<float>("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints", 720 new ParameterDefn<float>("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
683 5.0f, 721 5.0f ),
684 (s) => { return LinkConstraintTransMotorMaxVel; },
685 (s,v) => { LinkConstraintTransMotorMaxVel = v; } ),
686 new ParameterDefn<float>("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints", 722 new ParameterDefn<float>("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
687 0.1f, 723 0.1f ),
688 (s) => { return LinkConstraintTransMotorMaxForce; },
689 (s,v) => { LinkConstraintTransMotorMaxForce = v; } ),
690 new ParameterDefn<float>("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", 724 new ParameterDefn<float>("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
691 0.1f, 725 0.1f ),
692 (s) => { return LinkConstraintCFM; },
693 (s,v) => { LinkConstraintCFM = v; } ),
694 new ParameterDefn<float>("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", 726 new ParameterDefn<float>("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
695 0.1f, 727 0.1f ),
696 (s) => { return LinkConstraintERP; },
697 (s,v) => { LinkConstraintERP = v; } ),
698 new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", 728 new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
699 40, 729 40 ),
700 (s) => { return LinkConstraintSolverIterations; },
701 (s,v) => { LinkConstraintSolverIterations = v; } ),
702 730
703 new ParameterDefn<int>("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)", 731 new ParameterDefn<int>("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)",
704 0, 732 0,
@@ -707,7 +735,7 @@ public static class BSParam
707 new ParameterDefn<float>("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool", 735 new ParameterDefn<float>("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool",
708 0f, 736 0f,
709 (s) => { return 0f; }, 737 (s) => { return 0f; },
710 (s,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ), 738 (s,v) => { BSParam.ResetBroadphasePoolTainted(s, v, false /* inTaintTime */); } ),
711 new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver", 739 new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver",
712 0f, 740 0f,
713 (s) => { return 0f; }, 741 (s) => { return 0f; },
@@ -793,10 +821,10 @@ public static class BSParam
793 // ===================================================================== 821 // =====================================================================
794 // There are parameters that, when set, cause things to happen in the physics engine. 822 // There are parameters that, when set, cause things to happen in the physics engine.
795 // This causes the broadphase collision cache to be cleared. 823 // This causes the broadphase collision cache to be cleared.
796 private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v) 824 private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v, bool inTaintTime)
797 { 825 {
798 BSScene physScene = pPhysScene; 826 BSScene physScene = pPhysScene;
799 physScene.TaintedObject("BSParam.ResetBroadphasePoolTainted", delegate() 827 physScene.TaintedObject(inTaintTime, "BSParam.ResetBroadphasePoolTainted", delegate()
800 { 828 {
801 physScene.PE.ResetBroadphasePool(physScene.World); 829 physScene.PE.ResetBroadphasePool(physScene.World);
802 }); 830 });
@@ -806,7 +834,7 @@ public static class BSParam
806 private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v) 834 private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
807 { 835 {
808 BSScene physScene = pPhysScene; 836 BSScene physScene = pPhysScene;
809 physScene.TaintedObject("BSParam.ResetConstraintSolver", delegate() 837 physScene.TaintedObject(BSScene.DetailLogZero, "BSParam.ResetConstraintSolver", delegate()
810 { 838 {
811 physScene.PE.ResetConstraintSolver(physScene.World); 839 physScene.PE.ResetConstraintSolver(physScene.World);
812 }); 840 });
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 98ea833..f89b376 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -38,12 +38,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
38 * Class to wrap all objects. 38 * Class to wrap all objects.
39 * The rest of BulletSim doesn't need to keep checking for avatars or prims 39 * The rest of BulletSim doesn't need to keep checking for avatars or prims
40 * unless the difference is significant. 40 * unless the difference is significant.
41 * 41 *
42 * Variables in the physicsl objects are in three forms: 42 * Variables in the physicsl objects are in three forms:
43 * VariableName: used by the simulator and performs taint operations, etc 43 * VariableName: used by the simulator and performs taint operations, etc
44 * RawVariableName: direct reference to the BulletSim storage for the variable value 44 * RawVariableName: direct reference to the BulletSim storage for the variable value
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 one should only be referenced in taint-time.
47 */ 47 */
48 48
49/* 49/*
@@ -52,7 +52,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce 52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce
53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse 53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse
54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v 54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v
55 * BS.ApplyCentralForce BS.ApplyTorque 55 * BS.ApplyCentralForce BS.ApplyTorque
56 */ 56 */
57 57
58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc. 58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc.
@@ -72,22 +72,27 @@ public abstract class BSPhysObject : PhysicsActor
72 } 72 }
73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName) 73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
74 { 74 {
75 PhysicsScene = parentScene; 75 IsInitialized = false;
76
77 PhysScene = parentScene;
76 LocalID = localID; 78 LocalID = localID;
77 PhysObjectName = name; 79 PhysObjectName = name;
78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate. 80 Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
79 TypeName = typeName; 81 TypeName = typeName;
80 82
81 // The collection of things that push me around 83 // The collection of things that push me around
82 PhysicalActors = new BSActorCollection(PhysicsScene); 84 PhysicalActors = new BSActorCollection(PhysScene);
83 85
84 // Initialize variables kept in base. 86 // Initialize variables kept in base.
85 GravModifier = 1.0f; 87 GravModifier = 1.0f;
86 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity); 88 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
89 HoverActive = false;
87 90
88 // We don't have any physical representation yet. 91 // We don't have any physical representation yet.
89 PhysBody = new BulletBody(localID); 92 PhysBody = new BulletBody(localID);
90 PhysShape = new BulletShape(); 93 PhysShape = new BSShapeNull();
94
95 UserSetCenterOfMassDisplacement = null;
91 96
92 PrimAssetState = PrimAssetCondition.Unknown; 97 PrimAssetState = PrimAssetCondition.Unknown;
93 98
@@ -95,34 +100,41 @@ public abstract class BSPhysObject : PhysicsActor
95 SetMaterial((int)MaterialAttributes.Material.Wood); 100 SetMaterial((int)MaterialAttributes.Material.Wood);
96 101
97 CollisionCollection = new CollisionEventUpdate(); 102 CollisionCollection = new CollisionEventUpdate();
98 CollisionsLastTick = CollisionCollection; 103 CollisionsLastReported = CollisionCollection;
104 CollisionsLastTick = new CollisionEventUpdate();
105 CollisionsLastTickStep = -1;
106
99 SubscribedEventsMs = 0; 107 SubscribedEventsMs = 0;
100 CollidingStep = 0; 108 // Crazy values that will never be true
101 CollidingGroundStep = 0; 109 CollidingStep = BSScene.NotASimulationStep;
102 CollisionAccumulation = 0; 110 CollidingGroundStep = BSScene.NotASimulationStep;
111 CollisionAccumulation = BSScene.NotASimulationStep;
103 ColliderIsMoving = false; 112 ColliderIsMoving = false;
104 CollisionScore = 0; 113 CollisionScore = 0;
105 114
106 // All axis free. 115 // All axis free.
107 LockedAxis = LockedAxisFree; 116 LockedLinearAxis = LockedAxisFree;
117 LockedAngularAxis = LockedAxisFree;
108 } 118 }
109 119
110 // Tell the object to clean up. 120 // Tell the object to clean up.
111 public virtual void Destroy() 121 public virtual void Destroy()
112 { 122 {
113 UnRegisterAllPreStepActions(); 123 PhysicalActors.Enable(false);
114 UnRegisterAllPostStepActions(); 124 PhysScene.TaintedObject(LocalID, "BSPhysObject.Destroy", delegate()
115 PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate()
116 { 125 {
117 PhysicalActors.Release(); 126 PhysicalActors.Dispose();
118 }); 127 });
119 } 128 }
120 129
121 public BSScene PhysicsScene { get; protected set; } 130 public BSScene PhysScene { get; protected set; }
122 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 131 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
123 public string PhysObjectName { get; protected set; } 132 public string PhysObjectName { get; protected set; }
124 public string TypeName { get; protected set; } 133 public string TypeName { get; protected set; }
125 134
135 // Set to 'true' when the object is completely initialized.
136 // This mostly prevents property updates and collisions until the object is completely here.
137 public bool IsInitialized { get; protected set; }
126 138
127 // Return the object mass without calculating it or having side effects 139 // Return the object mass without calculating it or having side effects
128 public abstract float RawMass { get; } 140 public abstract float RawMass { get; }
@@ -138,26 +150,19 @@ public abstract class BSPhysObject : PhysicsActor
138 // Reference to the physical body (btCollisionObject) of this object 150 // Reference to the physical body (btCollisionObject) of this object
139 public BulletBody PhysBody; 151 public BulletBody PhysBody;
140 // Reference to the physical shape (btCollisionShape) of this object 152 // Reference to the physical shape (btCollisionShape) of this object
141 public BulletShape PhysShape; 153 public BSShape PhysShape;
142 154
143 // The physical representation of the prim might require an asset fetch. 155 // The physical representation of the prim might require an asset fetch.
144 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'. 156 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
145 public enum PrimAssetCondition 157 public enum PrimAssetCondition
146 { 158 {
147 Unknown, Waiting, Failed, Fetched 159 Unknown, Waiting, FailedAssetFetch, FailedMeshing, Fetched
148 } 160 }
149 public PrimAssetCondition PrimAssetState { get; set; } 161 public PrimAssetCondition PrimAssetState { get; set; }
150 162
151 // The objects base shape information. Null if not a prim type shape. 163 // The objects base shape information. Null if not a prim type shape.
152 public PrimitiveBaseShape BaseShape { get; protected set; } 164 public PrimitiveBaseShape BaseShape { get; protected set; }
153 165
154 // Some types of objects have preferred physical representations.
155 // Returns SHAPE_UNKNOWN if there is no preference.
156 public virtual BSPhysicsShapeType PreferredPhysicalShape
157 {
158 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
159 }
160
161 // When the physical properties are updated, an EntityProperty holds the update values. 166 // When the physical properties are updated, an EntityProperty holds the update values.
162 // Keep the current and last EntityProperties to enable computation of differences 167 // Keep the current and last EntityProperties to enable computation of differences
163 // between the current update and the previous values. 168 // between the current update and the previous values.
@@ -175,6 +180,7 @@ public abstract class BSPhysObject : PhysicsActor
175 public abstract bool IsSolid { get; } 180 public abstract bool IsSolid { get; }
176 public abstract bool IsStatic { get; } 181 public abstract bool IsStatic { get; }
177 public abstract bool IsSelected { get; } 182 public abstract bool IsSelected { get; }
183 public abstract bool IsVolumeDetect { get; }
178 184
179 // Materialness 185 // Materialness
180 public MaterialAttributes.Material Material { get; private set; } 186 public MaterialAttributes.Material Material { get; private set; }
@@ -183,13 +189,27 @@ public abstract class BSPhysObject : PhysicsActor
183 Material = (MaterialAttributes.Material)material; 189 Material = (MaterialAttributes.Material)material;
184 190
185 // Setting the material sets the material attributes also. 191 // Setting the material sets the material attributes also.
192 // TODO: decide if this is necessary -- the simulator does this.
186 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); 193 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
187 Friction = matAttrib.friction; 194 Friction = matAttrib.friction;
188 Restitution = matAttrib.restitution; 195 Restitution = matAttrib.restitution;
189 Density = matAttrib.density / BSParam.DensityScaleFactor; 196 Density = matAttrib.density;
190 // DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density); 197 // DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density);
191 } 198 }
192 199
200 public override float Density
201 {
202 get
203 {
204 return base.Density;
205 }
206 set
207 {
208 DetailLog("{0},BSPhysObject.Density,set,den={1}", LocalID, value);
209 base.Density = value;
210 }
211 }
212
193 // Stop all physical motion. 213 // Stop all physical motion.
194 public abstract void ZeroMotion(bool inTaintTime); 214 public abstract void ZeroMotion(bool inTaintTime);
195 public abstract void ZeroAngularMotion(bool inTaintTime); 215 public abstract void ZeroAngularMotion(bool inTaintTime);
@@ -197,21 +217,55 @@ public abstract class BSPhysObject : PhysicsActor
197 // Update the physical location and motion of the object. Called with data from Bullet. 217 // Update the physical location and motion of the object. Called with data from Bullet.
198 public abstract void UpdateProperties(EntityProperties entprop); 218 public abstract void UpdateProperties(EntityProperties entprop);
199 219
200 public abstract OMV.Vector3 RawPosition { get; set; } 220 public virtual OMV.Vector3 RawPosition { get; set; }
201 public abstract OMV.Vector3 ForcePosition { get; set; } 221 public abstract OMV.Vector3 ForcePosition { get; set; }
202 222
203 public abstract OMV.Quaternion RawOrientation { get; set; } 223 public virtual OMV.Quaternion RawOrientation { get; set; }
204 public abstract OMV.Quaternion ForceOrientation { get; set; } 224 public abstract OMV.Quaternion ForceOrientation { get; set; }
205 225
206 public abstract OMV.Vector3 RawVelocity { get; set; } 226 public OMV.Vector3 RawVelocity { get; set; }
207 public abstract OMV.Vector3 ForceVelocity { get; set; } 227 public abstract OMV.Vector3 ForceVelocity { get; set; }
208 228
229 public OMV.Vector3 RawForce { get; set; }
230 public OMV.Vector3 RawTorque { get; set; }
231 public override void AddAngularForce(OMV.Vector3 force, bool pushforce)
232 {
233 AddAngularForce(force, pushforce, false);
234 }
235 public abstract void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
236 public abstract void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
237
209 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 238 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
210 239
211 public abstract float ForceBuoyancy { get; set; } 240 public abstract float ForceBuoyancy { get; set; }
212 241
213 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 242 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
214 243
244 public override bool PIDActive { set { MoveToTargetActive = value; } }
245 public override OMV.Vector3 PIDTarget { set { MoveToTargetTarget = value; } }
246 public override float PIDTau { set { MoveToTargetTau = value; } }
247
248 public bool MoveToTargetActive { get; set; }
249 public OMV.Vector3 MoveToTargetTarget { get; set; }
250 public float MoveToTargetTau { get; set; }
251
252 // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z
253 public override bool PIDHoverActive { set { HoverActive = value; } }
254 public override float PIDHoverHeight { set { HoverHeight = value; } }
255 public override PIDHoverType PIDHoverType { set { HoverType = value; } }
256 public override float PIDHoverTau { set { HoverTau = value; } }
257
258 public bool HoverActive { get; set; }
259 public float HoverHeight { get; set; }
260 public PIDHoverType HoverType { get; set; }
261 public float HoverTau { get; set; }
262
263 // For RotLookAt
264 public override OMV.Quaternion APIDTarget { set { return; } }
265 public override bool APIDActive { set { return; } }
266 public override float APIDStrength { set { return; } }
267 public override float APIDDamping { set { return; } }
268
215 // The current velocity forward 269 // The current velocity forward
216 public virtual float ForwardSpeed 270 public virtual float ForwardSpeed
217 { 271 {
@@ -233,11 +287,69 @@ public abstract class BSPhysObject : PhysicsActor
233 287
234 // The user can optionally set the center of mass. The user's setting will override any 288 // The user can optionally set the center of mass. The user's setting will override any
235 // computed center-of-mass (like in linksets). 289 // computed center-of-mass (like in linksets).
236 public OMV.Vector3? UserSetCenterOfMass { get; set; } 290 // Note this is a displacement from the root's coordinates. Zero means use the root prim as center-of-mass.
291 public OMV.Vector3? UserSetCenterOfMassDisplacement { get; set; }
292
293 public OMV.Vector3 LockedLinearAxis { get; set; } // zero means locked. one means free.
294 public OMV.Vector3 LockedAngularAxis { get; set; } // zero means locked. one means free.
295 public const float FreeAxis = 1f;
296 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(FreeAxis, FreeAxis, FreeAxis); // All axis are free
297
298 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
299 // they need waking up when parameters are changed.
300 // Called in taint-time!!
301 public void ActivateIfPhysical(bool forceIt)
302 {
303 if (PhysBody.HasPhysicalBody)
304 {
305 if (IsPhysical)
306 {
307 // Physical objects might need activating
308 PhysScene.PE.Activate(PhysBody, forceIt);
309 }
310 else
311 {
312 // Clear the collision cache since we've changed some properties.
313 PhysScene.PE.ClearCollisionProxyCache(PhysScene.World, PhysBody);
314 }
315 }
316 }
237 317
238 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. 318 // 'actors' act on the physical object to change or constrain its motion. These can range from
239 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free 319 // hovering to complex vehicle motion.
240 public readonly String LockedAxisActorName = "BSPrim.LockedAxis"; 320 // May be called at non-taint time as this just adds the actor to the action list and the real
321 // work is done during the simulation step.
322 // Note that, if the actor is already in the list and we are disabling same, the actor is just left
323 // in the list disabled.
324 public delegate BSActor CreateActor();
325 public void EnableActor(bool enableActor, string actorName, CreateActor creator)
326 {
327 lock (PhysicalActors)
328 {
329 BSActor theActor;
330 if (PhysicalActors.TryGetActor(actorName, out theActor))
331 {
332 // The actor already exists so just turn it on or off
333 DetailLog("{0},BSPhysObject.EnableActor,enablingExistingActor,name={1},enable={2}", LocalID, actorName, enableActor);
334 theActor.Enabled = enableActor;
335 }
336 else
337 {
338 // The actor does not exist. If it should, create it.
339 if (enableActor)
340 {
341 DetailLog("{0},BSPhysObject.EnableActor,creatingActor,name={1}", LocalID, actorName);
342 theActor = creator();
343 PhysicalActors.Add(actorName, theActor);
344 theActor.Enabled = true;
345 }
346 else
347 {
348 DetailLog("{0},BSPhysObject.EnableActor,notCreatingActorSinceNotEnabled,name={1}", LocalID, actorName);
349 }
350 }
351 }
352 }
241 353
242 #region Collisions 354 #region Collisions
243 355
@@ -255,70 +367,98 @@ public abstract class BSPhysObject : PhysicsActor
255 protected CollisionFlags CurrentCollisionFlags { get; set; } 367 protected CollisionFlags CurrentCollisionFlags { get; set; }
256 // On a collision, check the collider and remember if the last collider was moving 368 // On a collision, check the collider and remember if the last collider was moving
257 // Used to modify the standing of avatars (avatars on stationary things stand still) 369 // Used to modify the standing of avatars (avatars on stationary things stand still)
258 protected bool ColliderIsMoving; 370 public bool ColliderIsMoving;
371 // 'true' if the last collider was a volume detect object
372 public bool ColliderIsVolumeDetect;
373 // Used by BSCharacter to manage standing (and not slipping)
374 public bool IsStationary;
259 375
260 // Count of collisions for this object 376 // Count of collisions for this object
261 protected long CollisionAccumulation { get; set; } 377 protected long CollisionAccumulation { get; set; }
262 378
263 public override bool IsColliding { 379 public override bool IsColliding {
264 get { return (CollidingStep == PhysicsScene.SimulationStep); } 380 get { return (CollidingStep == PhysScene.SimulationStep); }
265 set { 381 set {
266 if (value) 382 if (value)
267 CollidingStep = PhysicsScene.SimulationStep; 383 CollidingStep = PhysScene.SimulationStep;
268 else 384 else
269 CollidingStep = 0; 385 CollidingStep = BSScene.NotASimulationStep;
270 } 386 }
271 } 387 }
388 // Complex objects (like linksets) need to know if there is a collision on any part of
389 // their shape. 'IsColliding' has an existing definition of reporting a collision on
390 // only this specific prim or component of linksets.
391 // 'HasSomeCollision' is defined as reporting if there is a collision on any part of
392 // the complex body that this prim is the root of.
393 public virtual bool HasSomeCollision
394 {
395 get { return IsColliding; }
396 set { IsColliding = value; }
397 }
272 public override bool CollidingGround { 398 public override bool CollidingGround {
273 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 399 get { return (CollidingGroundStep == PhysScene.SimulationStep); }
274 set 400 set
275 { 401 {
276 if (value) 402 if (value)
277 CollidingGroundStep = PhysicsScene.SimulationStep; 403 CollidingGroundStep = PhysScene.SimulationStep;
278 else 404 else
279 CollidingGroundStep = 0; 405 CollidingGroundStep = BSScene.NotASimulationStep;
280 } 406 }
281 } 407 }
282 public override bool CollidingObj { 408 public override bool CollidingObj {
283 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } 409 get { return (CollidingObjectStep == PhysScene.SimulationStep); }
284 set { 410 set {
285 if (value) 411 if (value)
286 CollidingObjectStep = PhysicsScene.SimulationStep; 412 CollidingObjectStep = PhysScene.SimulationStep;
287 else 413 else
288 CollidingObjectStep = 0; 414 CollidingObjectStep = BSScene.NotASimulationStep;
289 } 415 }
290 } 416 }
291 417
292 // The collisions that have been collected this tick 418 // The collisions that have been collected for the next collision reporting (throttled by subscription)
293 protected CollisionEventUpdate CollisionCollection; 419 protected CollisionEventUpdate CollisionCollection;
294 // Remember collisions from last tick for fancy collision based actions 420 // This is the collision collection last reported to the Simulator.
421 public CollisionEventUpdate CollisionsLastReported;
422 // Remember the collisions recorded in the last tick for fancy collision checking
295 // (like a BSCharacter walking up stairs). 423 // (like a BSCharacter walking up stairs).
296 protected CollisionEventUpdate CollisionsLastTick; 424 public CollisionEventUpdate CollisionsLastTick;
425 private long CollisionsLastTickStep = -1;
297 426
298 // The simulation step is telling this object about a collision. 427 // The simulation step is telling this object about a collision.
299 // Return 'true' if a collision was processed and should be sent up. 428 // Return 'true' if a collision was processed and should be sent up.
300 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision. 429 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision.
301 // Called at taint time from within the Step() function 430 // Called at taint time from within the Step() function
431 public delegate bool CollideCall(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
302 public virtual bool Collide(uint collidingWith, BSPhysObject collidee, 432 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
303 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 433 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
304 { 434 {
305 bool ret = false; 435 bool ret = false;
306 436
307 // The following lines make IsColliding(), CollidingGround() and CollidingObj work 437 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
308 CollidingStep = PhysicsScene.SimulationStep; 438 CollidingStep = PhysScene.SimulationStep;
309 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 439 if (collidingWith <= PhysScene.TerrainManager.HighestTerrainID)
310 { 440 {
311 CollidingGroundStep = PhysicsScene.SimulationStep; 441 CollidingGroundStep = PhysScene.SimulationStep;
312 } 442 }
313 else 443 else
314 { 444 {
315 CollidingObjectStep = PhysicsScene.SimulationStep; 445 CollidingObjectStep = PhysScene.SimulationStep;
316 } 446 }
317 447
318 CollisionAccumulation++; 448 CollisionAccumulation++;
319 449
320 // For movement tests, remember if we are colliding with an object that is moving. 450 // For movement tests, remember if we are colliding with an object that is moving.
321 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false; 451 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false;
452 ColliderIsVolumeDetect = collidee != null ? (collidee.IsVolumeDetect) : false;
453
454 // Make a collection of the collisions that happened the last simulation tick.
455 // This is different than the collection created for sending up to the simulator as it is cleared every tick.
456 if (CollisionsLastTickStep != PhysScene.SimulationStep)
457 {
458 CollisionsLastTick = new CollisionEventUpdate();
459 CollisionsLastTickStep = PhysScene.SimulationStep;
460 }
461 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
322 462
323 // If someone has subscribed for collision events log the collision so it will be reported up 463 // If someone has subscribed for collision events log the collision so it will be reported up
324 if (SubscribedEvents()) { 464 if (SubscribedEvents()) {
@@ -340,12 +480,12 @@ public abstract class BSPhysObject : PhysicsActor
340 bool ret = true; 480 bool ret = true;
341 481
342 // If the 'no collision' call, force it to happen right now so quick collision_end 482 // If the 'no collision' call, force it to happen right now so quick collision_end
343 bool force = (CollisionCollection.Count == 0 && CollisionsLastTick.Count != 0); 483 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
344 484
345 // throttle the collisions to the number of milliseconds specified in the subscription 485 // throttle the collisions to the number of milliseconds specified in the subscription
346 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 486 if (force || (PhysScene.SimulationNowTime >= NextCollisionOkTime))
347 { 487 {
348 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; 488 NextCollisionOkTime = PhysScene.SimulationNowTime + SubscribedEventsMs;
349 489
350 // We are called if we previously had collisions. If there are no collisions 490 // We are called if we previously had collisions. If there are no collisions
351 // this time, send up one last empty event so OpenSim can sense collision end. 491 // this time, send up one last empty event so OpenSim can sense collision end.
@@ -359,11 +499,11 @@ public abstract class BSPhysObject : PhysicsActor
359 base.SendCollisionUpdate(CollisionCollection); 499 base.SendCollisionUpdate(CollisionCollection);
360 500
361 // Remember the collisions from this tick for some collision specific processing. 501 // Remember the collisions from this tick for some collision specific processing.
362 CollisionsLastTick = CollisionCollection; 502 CollisionsLastReported = CollisionCollection;
363 503
364 // The CollisionCollection instance is passed around in the simulator. 504 // The CollisionCollection instance is passed around in the simulator.
365 // Make sure we don't have a handle to that one and that a new one is used for next time. 505 // Make sure we don't have a handle to that one and that a new one is used for next time.
366 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, 506 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
367 // a race condition is created for the other users of this instance. 507 // a race condition is created for the other users of this instance.
368 CollisionCollection = new CollisionEventUpdate(); 508 CollisionCollection = new CollisionEventUpdate();
369 } 509 }
@@ -380,10 +520,10 @@ public abstract class BSPhysObject : PhysicsActor
380 // make sure first collision happens 520 // make sure first collision happens
381 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 521 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
382 522
383 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 523 PhysScene.TaintedObject(LocalID, TypeName+".SubscribeEvents", delegate()
384 { 524 {
385 if (PhysBody.HasPhysicalBody) 525 if (PhysBody.HasPhysicalBody)
386 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 526 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
387 }); 527 });
388 } 528 }
389 else 529 else
@@ -395,11 +535,11 @@ public abstract class BSPhysObject : PhysicsActor
395 public override void UnSubscribeEvents() { 535 public override void UnSubscribeEvents() {
396 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); 536 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
397 SubscribedEventsMs = 0; 537 SubscribedEventsMs = 0;
398 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 538 PhysScene.TaintedObject(LocalID, TypeName+".UnSubscribeEvents", delegate()
399 { 539 {
400 // Make sure there is a body there because sometimes destruction happens in an un-ideal order. 540 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
401 if (PhysBody.HasPhysicalBody) 541 if (PhysBody.HasPhysicalBody)
402 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 542 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
403 }); 543 });
404 } 544 }
405 // Return 'true' if the simulator wants collision events 545 // Return 'true' if the simulator wants collision events
@@ -413,7 +553,7 @@ public abstract class BSPhysObject : PhysicsActor
413 { 553 {
414 // Scale the collision count by the time since the last collision. 554 // Scale the collision count by the time since the last collision.
415 // The "+1" prevents dividing by zero. 555 // The "+1" prevents dividing by zero.
416 long timeAgo = PhysicsScene.SimulationStep - CollidingStep + 1; 556 long timeAgo = PhysScene.SimulationStep - CollidingStep + 1;
417 CollisionScore = CollisionAccumulation / timeAgo; 557 CollisionScore = CollisionAccumulation / timeAgo;
418 } 558 }
419 public override float CollisionScore { get; set; } 559 public override float CollisionScore { get; set; }
@@ -424,104 +564,6 @@ public abstract class BSPhysObject : PhysicsActor
424 564
425 public BSActorCollection PhysicalActors; 565 public BSActorCollection PhysicalActors;
426 566
427 // There are some actions that must be performed for a physical object before each simulation step.
428 // These actions are optional so, rather than scanning all the physical objects and asking them
429 // if they have anything to do, a physical object registers for an event call before the step is performed.
430 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
431 private Dictionary<string, BSScene.PreStepAction> RegisteredPrestepActions = new Dictionary<string, BSScene.PreStepAction>();
432 private Dictionary<string, BSScene.PostStepAction> RegisteredPoststepActions = new Dictionary<string, BSScene.PostStepAction>();
433 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
434 {
435 string identifier = op + "-" + id.ToString();
436
437 lock (RegisteredPrestepActions)
438 {
439 // Clean out any existing action
440 UnRegisterPreStepAction(op, id);
441 RegisteredPrestepActions[identifier] = actn;
442 PhysicsScene.BeforeStep += actn;
443 }
444 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
445 }
446
447 // Unregister a pre step action. Safe to call if the action has not been registered.
448 // Returns 'true' if an action was actually removed
449 protected bool UnRegisterPreStepAction(string op, uint id)
450 {
451 string identifier = op + "-" + id.ToString();
452 bool removed = false;
453 lock (RegisteredPrestepActions)
454 {
455 if (RegisteredPrestepActions.ContainsKey(identifier))
456 {
457 PhysicsScene.BeforeStep -= RegisteredPrestepActions[identifier];
458 RegisteredPrestepActions.Remove(identifier);
459 removed = true;
460 }
461 }
462 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
463 return removed;
464 }
465
466 protected void UnRegisterAllPreStepActions()
467 {
468 lock (RegisteredPrestepActions)
469 {
470 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredPrestepActions)
471 {
472 PhysicsScene.BeforeStep -= kvp.Value;
473 }
474 RegisteredPrestepActions.Clear();
475 }
476 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
477 }
478
479 protected void RegisterPostStepAction(string op, uint id, BSScene.PostStepAction actn)
480 {
481 string identifier = op + "-" + id.ToString();
482
483 lock (RegisteredPoststepActions)
484 {
485 // Clean out any existing action
486 UnRegisterPostStepAction(op, id);
487 RegisteredPoststepActions[identifier] = actn;
488 PhysicsScene.AfterStep += actn;
489 }
490 DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
491 }
492
493 // Unregister a pre step action. Safe to call if the action has not been registered.
494 // Returns 'true' if an action was actually removed.
495 protected bool UnRegisterPostStepAction(string op, uint id)
496 {
497 string identifier = op + "-" + id.ToString();
498 bool removed = false;
499 lock (RegisteredPoststepActions)
500 {
501 if (RegisteredPoststepActions.ContainsKey(identifier))
502 {
503 PhysicsScene.AfterStep -= RegisteredPoststepActions[identifier];
504 RegisteredPoststepActions.Remove(identifier);
505 removed = true;
506 }
507 }
508 DetailLog("{0},BSPhysObject.UnRegisterPostStepAction,id={1},removed={2}", LocalID, identifier, removed);
509 return removed;
510 }
511
512 protected void UnRegisterAllPostStepActions()
513 {
514 lock (RegisteredPoststepActions)
515 {
516 foreach (KeyValuePair<string, BSScene.PostStepAction> kvp in RegisteredPoststepActions)
517 {
518 PhysicsScene.AfterStep -= kvp.Value;
519 }
520 RegisteredPoststepActions.Clear();
521 }
522 DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
523 }
524
525 // When an update to the physical properties happens, this event is fired to let 567 // When an update to the physical properties happens, this event is fired to let
526 // different actors to modify the update before it is passed around 568 // different actors to modify the update before it is passed around
527 public delegate void PreUpdatePropertyAction(ref EntityProperties entprop); 569 public delegate void PreUpdatePropertyAction(ref EntityProperties entprop);
@@ -533,53 +575,13 @@ public abstract class BSPhysObject : PhysicsActor
533 actions(ref entprop); 575 actions(ref entprop);
534 } 576 }
535 577
536 private Dictionary<string, PreUpdatePropertyAction> RegisteredPreUpdatePropertyActions = new Dictionary<string, PreUpdatePropertyAction>();
537 public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn)
538 {
539 lock (RegisteredPreUpdatePropertyActions)
540 {
541 // Clean out any existing action
542 UnRegisterPreUpdatePropertyAction(identifier);
543 RegisteredPreUpdatePropertyActions[identifier] = actn;
544 OnPreUpdateProperty += actn;
545 }
546 DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier);
547 }
548 public bool UnRegisterPreUpdatePropertyAction(string identifier)
549 {
550 bool removed = false;
551 lock (RegisteredPreUpdatePropertyActions)
552 {
553 if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier))
554 {
555 OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier];
556 RegisteredPreUpdatePropertyActions.Remove(identifier);
557 removed = true;
558 }
559 }
560 DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed);
561 return removed;
562 }
563 public void UnRegisterAllPreUpdatePropertyActions()
564 {
565 lock (RegisteredPreUpdatePropertyActions)
566 {
567 foreach (KeyValuePair<string, PreUpdatePropertyAction> kvp in RegisteredPreUpdatePropertyActions)
568 {
569 OnPreUpdateProperty -= kvp.Value;
570 }
571 RegisteredPreUpdatePropertyActions.Clear();
572 }
573 DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID);
574 }
575
576 #endregion // Per Simulation Step actions 578 #endregion // Per Simulation Step actions
577 579
578 // High performance detailed logging routine used by the physical objects. 580 // High performance detailed logging routine used by the physical objects.
579 protected void DetailLog(string msg, params Object[] args) 581 protected void DetailLog(string msg, params Object[] args)
580 { 582 {
581 if (PhysicsScene.PhysicsLogging.Enabled) 583 if (PhysScene.PhysicsLogging.Enabled)
582 PhysicsScene.DetailLog(msg, args); 584 PhysScene.DetailLog(msg, args);
583 } 585 }
584 586
585} 587}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index e56276a..15b7090 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
41 [Serializable] 41 [Serializable]
42public class BSPrim : BSPhysObject 42public class BSPrim : BSPhysObject
43{ 43{
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
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.
@@ -51,15 +51,8 @@ public class BSPrim : BSPhysObject
51 private bool _isSelected; 51 private bool _isSelected;
52 private bool _isVolumeDetect; 52 private bool _isVolumeDetect;
53 53
54 // _position is what the simulator thinks the positions of the prim is.
55 private OMV.Vector3 _position;
56
57 private float _mass; // the mass of this object 54 private float _mass; // the mass of this object
58 private OMV.Vector3 _force;
59 private OMV.Vector3 _velocity;
60 private OMV.Vector3 _torque;
61 private OMV.Vector3 _acceleration; 55 private OMV.Vector3 _acceleration;
62 private OMV.Quaternion _orientation;
63 private int _physicsActorType; 56 private int _physicsActorType;
64 private bool _isPhysical; 57 private bool _isPhysical;
65 private bool _flying; 58 private bool _flying;
@@ -72,17 +65,18 @@ public class BSPrim : BSPhysObject
72 65
73 private int CrossingFailures { get; set; } 66 private int CrossingFailures { get; set; }
74 67
75 public BSDynamics VehicleActor; 68 // Keep a handle to the vehicle actor so it is easy to set parameters on same.
76 public string VehicleActorName = "BasicVehicle"; 69 public const string VehicleActorName = "BasicVehicle";
77
78 private BSVMotor _targetMotor;
79 private OMV.Vector3 _PIDTarget;
80 private float _PIDTau;
81 70
82 private BSFMotor _hoverMotor; 71 // Parameters for the hover actor
83 private float _PIDHoverHeight; 72 public const string HoverActorName = "BSPrim.HoverActor";
84 private PIDHoverType _PIDHoverType; 73 // Parameters for the axis lock actor
85 private float _PIDHoverTau; 74 public const String LockedAxisActorName = "BSPrim.LockedAxis";
75 // Parameters for the move to target actor
76 public const string MoveToTargetActorName = "BSPrim.MoveToTargetActor";
77 // Parameters for the setForce and setTorque actors
78 public const string SetForceActorName = "BSPrim.SetForceActor";
79 public const string SetTorqueActorName = "BSPrim.SetTorqueActor";
86 80
87 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 81 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
88 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 82 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
@@ -90,32 +84,34 @@ public class BSPrim : BSPhysObject
90 { 84 {
91 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 85 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
92 _physicsActorType = (int)ActorTypes.Prim; 86 _physicsActorType = (int)ActorTypes.Prim;
93 _position = pos; 87 RawPosition = pos;
94 _size = size; 88 _size = size;
95 Scale = size; // prims are the size the user wants them to be (different for BSCharactes). 89 Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
96 _orientation = rotation; 90 RawOrientation = rotation;
97 _buoyancy = 0f; 91 _buoyancy = 0f;
98 _velocity = OMV.Vector3.Zero; 92 RawVelocity = OMV.Vector3.Zero;
99 _rotationalVelocity = OMV.Vector3.Zero; 93 _rotationalVelocity = OMV.Vector3.Zero;
100 BaseShape = pbs; 94 BaseShape = pbs;
101 _isPhysical = pisPhysical; 95 _isPhysical = pisPhysical;
102 _isVolumeDetect = false; 96 _isVolumeDetect = false;
103 97
104 VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName); 98 // Add a dynamic vehicle to our set of actors that can move this prim.
105 PhysicalActors.Add(VehicleActorName, VehicleActor); 99 // PhysicalActors.Add(VehicleActorName, new BSDynamics(PhysScene, this, VehicleActorName));
106 100
107 _mass = CalculateMass(); 101 _mass = CalculateMass();
108 102
109 // DetailLog("{0},BSPrim.constructor,call", LocalID); 103 // DetailLog("{0},BSPrim.constructor,call", LocalID);
110 // do the actual object creation at taint time 104 // do the actual object creation at taint time
111 PhysicsScene.TaintedObject("BSPrim.create", delegate() 105 PhysScene.TaintedObject(LocalID, "BSPrim.create", delegate()
112 { 106 {
113 // Make sure the object is being created with some sanity. 107 // Make sure the object is being created with some sanity.
114 ExtremeSanityCheck(true /* inTaintTime */); 108 ExtremeSanityCheck(true /* inTaintTime */);
115 109
116 CreateGeomAndObject(true); 110 CreateGeomAndObject(true);
117 111
118 CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody); 112 CurrentCollisionFlags = PhysScene.PE.GetCollisionFlags(PhysBody);
113
114 IsInitialized = true;
119 }); 115 });
120 } 116 }
121 117
@@ -123,19 +119,21 @@ public class BSPrim : BSPhysObject
123 public override void Destroy() 119 public override void Destroy()
124 { 120 {
125 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 121 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
122 IsInitialized = false;
123
126 base.Destroy(); 124 base.Destroy();
127 125
128 // Undo any vehicle properties 126 // Undo any vehicle properties
129 this.VehicleType = (int)Vehicle.TYPE_NONE; 127 this.VehicleType = (int)Vehicle.TYPE_NONE;
130 128
131 PhysicsScene.TaintedObject("BSPrim.Destroy", delegate() 129 PhysScene.TaintedObject(LocalID, "BSPrim.Destroy", delegate()
132 { 130 {
133 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 131 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
134 // If there are physical body and shape, release my use of same. 132 // If there are physical body and shape, release my use of same.
135 PhysicsScene.Shapes.DereferenceBody(PhysBody, null); 133 PhysScene.Shapes.DereferenceBody(PhysBody, null);
136 PhysBody.Clear(); 134 PhysBody.Clear();
137 PhysicsScene.Shapes.DereferenceShape(PhysShape, null); 135 PhysShape.Dereference(PhysScene);
138 PhysShape.Clear(); 136 PhysShape = new BSShapeNull();
139 }); 137 });
140 } 138 }
141 139
@@ -161,25 +159,13 @@ public class BSPrim : BSPhysObject
161 ForceBodyShapeRebuild(false); 159 ForceBodyShapeRebuild(false);
162 } 160 }
163 } 161 }
164 // 'unknown' says to choose the best type
165 public override BSPhysicsShapeType PreferredPhysicalShape
166 { get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } }
167
168 public override bool ForceBodyShapeRebuild(bool inTaintTime) 162 public override bool ForceBodyShapeRebuild(bool inTaintTime)
169 { 163 {
170 if (inTaintTime) 164 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ForceBodyShapeRebuild", delegate()
171 { 165 {
172 _mass = CalculateMass(); // changing the shape changes the mass 166 _mass = CalculateMass(); // changing the shape changes the mass
173 CreateGeomAndObject(true); 167 CreateGeomAndObject(true);
174 } 168 });
175 else
176 {
177 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
178 {
179 _mass = CalculateMass(); // changing the shape changes the mass
180 CreateGeomAndObject(true);
181 });
182 }
183 return true; 169 return true;
184 } 170 }
185 public override bool Grabbed { 171 public override bool Grabbed {
@@ -192,7 +178,7 @@ public class BSPrim : BSPhysObject
192 if (value != _isSelected) 178 if (value != _isSelected)
193 { 179 {
194 _isSelected = value; 180 _isSelected = value;
195 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() 181 PhysScene.TaintedObject(LocalID, "BSPrim.setSelected", delegate()
196 { 182 {
197 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); 183 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
198 SetObjectDynamic(false); 184 SetObjectDynamic(false);
@@ -233,28 +219,28 @@ public class BSPrim : BSPhysObject
233 // Called at taint time! 219 // Called at taint time!
234 public override void ZeroMotion(bool inTaintTime) 220 public override void ZeroMotion(bool inTaintTime)
235 { 221 {
236 _velocity = OMV.Vector3.Zero; 222 RawVelocity = OMV.Vector3.Zero;
237 _acceleration = OMV.Vector3.Zero; 223 _acceleration = OMV.Vector3.Zero;
238 _rotationalVelocity = OMV.Vector3.Zero; 224 _rotationalVelocity = OMV.Vector3.Zero;
239 225
240 // Zero some other properties in the physics engine 226 // Zero some other properties in the physics engine
241 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 227 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate()
242 { 228 {
243 if (PhysBody.HasPhysicalBody) 229 if (PhysBody.HasPhysicalBody)
244 PhysicsScene.PE.ClearAllForces(PhysBody); 230 PhysScene.PE.ClearAllForces(PhysBody);
245 }); 231 });
246 } 232 }
247 public override void ZeroAngularMotion(bool inTaintTime) 233 public override void ZeroAngularMotion(bool inTaintTime)
248 { 234 {
249 _rotationalVelocity = OMV.Vector3.Zero; 235 _rotationalVelocity = OMV.Vector3.Zero;
250 // Zero some other properties in the physics engine 236 // Zero some other properties in the physics engine
251 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 237 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate()
252 { 238 {
253 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); 239 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
254 if (PhysBody.HasPhysicalBody) 240 if (PhysBody.HasPhysicalBody)
255 { 241 {
256 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 242 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
257 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 243 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
258 } 244 }
259 }); 245 });
260 } 246 }
@@ -268,64 +254,58 @@ public class BSPrim : BSPhysObject
268 if (axis.X != 1) locking.X = 0f; 254 if (axis.X != 1) locking.X = 0f;
269 if (axis.Y != 1) locking.Y = 0f; 255 if (axis.Y != 1) locking.Y = 0f;
270 if (axis.Z != 1) locking.Z = 0f; 256 if (axis.Z != 1) locking.Z = 0f;
271 LockedAxis = locking; 257 LockedAngularAxis = locking;
272 258
273 if (LockedAxis != LockedAxisFree) 259 EnableActor(LockedAngularAxis != LockedAxisFree, LockedAxisActorName, delegate()
274 { 260 {
275 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() 261 return new BSActorLockAxis(PhysScene, this, LockedAxisActorName);
276 { 262 });
277 // If there is not already an axis locker, make one 263
278 if (!PhysicalActors.HasActor(LockedAxisActorName)) 264 // Update parameters so the new actor's Refresh() action is called at the right time.
279 { 265 PhysScene.TaintedObject(LocalID, "BSPrim.LockAngularMotion", delegate()
280 DetailLog("{0},BSPrim.LockAngularMotion,taint,registeringLockAxisActor", LocalID); 266 {
281 PhysicalActors.Add(LockedAxisActorName, new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName)); 267 UpdatePhysicalParameters();
282 } 268 });
283 UpdatePhysicalParameters(); 269
284 });
285 }
286 return; 270 return;
287 } 271 }
288 272
289 public override OMV.Vector3 RawPosition
290 {
291 get { return _position; }
292 set { _position = value; }
293 }
294 public override OMV.Vector3 Position { 273 public override OMV.Vector3 Position {
295 get { 274 get {
296 // don't do the GetObjectPosition for root elements because this function is called a zillion times. 275 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
297 // _position = ForcePosition; 276 // RawPosition = ForcePosition;
298 return _position; 277 return RawPosition;
299 } 278 }
300 set { 279 set {
301 // If the position must be forced into the physics engine, use ForcePosition. 280 // If the position must be forced into the physics engine, use ForcePosition.
302 // All positions are given in world positions. 281 // All positions are given in world positions.
303 if (_position == value) 282 if (RawPosition == value)
304 { 283 {
305 DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation); 284 DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
306 return; 285 return;
307 } 286 }
308 _position = value; 287 RawPosition = value;
309 PositionSanityCheck(false); 288 PositionSanityCheck(false);
310 289
311 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 290 PhysScene.TaintedObject(LocalID, "BSPrim.setPosition", delegate()
312 { 291 {
313 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 292 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
314 ForcePosition = _position; 293 ForcePosition = RawPosition;
315 }); 294 });
316 } 295 }
317 } 296 }
318 297
298 // NOTE: overloaded by BSPrimDisplaced to handle offset for center-of-gravity.
319 public override OMV.Vector3 ForcePosition { 299 public override OMV.Vector3 ForcePosition {
320 get { 300 get {
321 _position = PhysicsScene.PE.GetPosition(PhysBody); 301 RawPosition = PhysScene.PE.GetPosition(PhysBody);
322 return _position; 302 return RawPosition;
323 } 303 }
324 set { 304 set {
325 _position = value; 305 RawPosition = value;
326 if (PhysBody.HasPhysicalBody) 306 if (PhysBody.HasPhysicalBody)
327 { 307 {
328 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 308 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
329 ActivateIfPhysical(false); 309 ActivateIfPhysical(false);
330 } 310 }
331 } 311 }
@@ -342,7 +322,7 @@ public class BSPrim : BSPhysObject
342 if (!IsPhysicallyActive) 322 if (!IsPhysicallyActive)
343 return ret; 323 return ret;
344 324
345 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) 325 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
346 { 326 {
347 // The physical object is out of the known/simulated area. 327 // The physical object is out of the known/simulated area.
348 // Upper levels of code will handle the transition to other areas so, for 328 // Upper levels of code will handle the transition to other areas so, for
@@ -350,7 +330,7 @@ public class BSPrim : BSPhysObject
350 return ret; 330 return ret;
351 } 331 }
352 332
353 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); 333 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
354 OMV.Vector3 upForce = OMV.Vector3.Zero; 334 OMV.Vector3 upForce = OMV.Vector3.Zero;
355 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z)); 335 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z));
356 if ((RawPosition.Z + approxSize / 2f) < terrainHeight) 336 if ((RawPosition.Z + approxSize / 2f) < terrainHeight)
@@ -359,10 +339,10 @@ public class BSPrim : BSPhysObject
359 float targetHeight = terrainHeight + (Size.Z / 2f); 339 float targetHeight = terrainHeight + (Size.Z / 2f);
360 // If the object is below ground it just has to be moved up because pushing will 340 // If the object is below ground it just has to be moved up because pushing will
361 // not get it through the terrain 341 // not get it through the terrain
362 _position.Z = targetHeight; 342 RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, targetHeight);
363 if (inTaintTime) 343 if (inTaintTime)
364 { 344 {
365 ForcePosition = _position; 345 ForcePosition = RawPosition;
366 } 346 }
367 // If we are throwing the object around, zero its other forces 347 // If we are throwing the object around, zero its other forces
368 ZeroMotion(inTaintTime); 348 ZeroMotion(inTaintTime);
@@ -371,7 +351,7 @@ public class BSPrim : BSPhysObject
371 351
372 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 352 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
373 { 353 {
374 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); 354 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
375 // TODO: a floating motor so object will bob in the water 355 // TODO: a floating motor so object will bob in the water
376 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) 356 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f)
377 { 357 {
@@ -379,8 +359,8 @@ public class BSPrim : BSPhysObject
379 upForce.Z = (waterHeight - RawPosition.Z) * 1f; 359 upForce.Z = (waterHeight - RawPosition.Z) * 1f;
380 360
381 // Apply upforce and overcome gravity. 361 // Apply upforce and overcome gravity.
382 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; 362 OMV.Vector3 correctionForce = upForce - PhysScene.DefaultGravity;
383 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce); 363 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, RawPosition, upForce, correctionForce);
384 AddForce(correctionForce, false, inTaintTime); 364 AddForce(correctionForce, false, inTaintTime);
385 ret = true; 365 ret = true;
386 } 366 }
@@ -399,17 +379,17 @@ public class BSPrim : BSPhysObject
399 uint wayOutThere = Constants.RegionSize * Constants.RegionSize; 379 uint wayOutThere = Constants.RegionSize * Constants.RegionSize;
400 // There have been instances of objects getting thrown way out of bounds and crashing 380 // There have been instances of objects getting thrown way out of bounds and crashing
401 // the border crossing code. 381 // the border crossing code.
402 if ( _position.X < -Constants.RegionSize || _position.X > wayOutThere 382 if ( RawPosition.X < -Constants.RegionSize || RawPosition.X > wayOutThere
403 || _position.Y < -Constants.RegionSize || _position.Y > wayOutThere 383 || RawPosition.Y < -Constants.RegionSize || RawPosition.Y > wayOutThere
404 || _position.Z < -Constants.RegionSize || _position.Z > wayOutThere) 384 || RawPosition.Z < -Constants.RegionSize || RawPosition.Z > wayOutThere)
405 { 385 {
406 _position = new OMV.Vector3(10, 10, 50); 386 RawPosition = new OMV.Vector3(10, 10, 50);
407 ZeroMotion(inTaintTime); 387 ZeroMotion(inTaintTime);
408 ret = true; 388 ret = true;
409 } 389 }
410 if (_velocity.LengthSquared() > BSParam.MaxLinearVelocity) 390 if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity)
411 { 391 {
412 _velocity = Util.ClampV(_velocity, BSParam.MaxLinearVelocity); 392 RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity);
413 ret = true; 393 ret = true;
414 } 394 }
415 if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) 395 if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared)
@@ -434,7 +414,7 @@ public class BSPrim : BSPhysObject
434 get { return _mass; } 414 get { return _mass; }
435 } 415 }
436 // used when we only want this prim's mass and not the linkset thing 416 // used when we only want this prim's mass and not the linkset thing
437 public override float RawMass { 417 public override float RawMass {
438 get { return _mass; } 418 get { return _mass; }
439 } 419 }
440 // Set the physical mass to the passed mass. 420 // Set the physical mass to the passed mass.
@@ -445,10 +425,10 @@ public class BSPrim : BSPhysObject
445 { 425 {
446 if (IsStatic) 426 if (IsStatic)
447 { 427 {
448 PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity); 428 PhysScene.PE.SetGravity(PhysBody, PhysScene.DefaultGravity);
449 Inertia = OMV.Vector3.Zero; 429 Inertia = OMV.Vector3.Zero;
450 PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia); 430 PhysScene.PE.SetMassProps(PhysBody, 0f, Inertia);
451 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 431 PhysScene.PE.UpdateInertiaTensor(PhysBody);
452 } 432 }
453 else 433 else
454 { 434 {
@@ -457,16 +437,19 @@ public class BSPrim : BSPhysObject
457 // Changing interesting properties doesn't change proxy and collision cache 437 // Changing interesting properties doesn't change proxy and collision cache
458 // information. The Bullet solution is to re-add the object to the world 438 // information. The Bullet solution is to re-add the object to the world
459 // after parameters are changed. 439 // after parameters are changed.
460 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 440 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
461 } 441 }
462 442
463 // The computation of mass props requires gravity to be set on the object. 443 // The computation of mass props requires gravity to be set on the object.
464 Gravity = ComputeGravity(Buoyancy); 444 Gravity = ComputeGravity(Buoyancy);
465 PhysicsScene.PE.SetGravity(PhysBody, Gravity); 445 PhysScene.PE.SetGravity(PhysBody, Gravity);
446
447 // OMV.Vector3 currentScale = PhysScene.PE.GetLocalScaling(PhysShape.physShapeInfo); // DEBUG DEBUG
448 // DetailLog("{0},BSPrim.UpdateMassProperties,currentScale{1},shape={2}", LocalID, currentScale, PhysShape.physShapeInfo); // DEBUG DEBUG
466 449
467 Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); 450 Inertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
468 PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); 451 PhysScene.PE.SetMassProps(PhysBody, physMass, Inertia);
469 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 452 PhysScene.PE.UpdateInertiaTensor(PhysBody);
470 453
471 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", 454 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}",
472 LocalID, physMass, Inertia, Gravity, inWorld); 455 LocalID, physMass, Inertia, Gravity, inWorld);
@@ -482,7 +465,7 @@ public class BSPrim : BSPhysObject
482 // Return what gravity should be set to this very moment 465 // Return what gravity should be set to this very moment
483 public OMV.Vector3 ComputeGravity(float buoyancy) 466 public OMV.Vector3 ComputeGravity(float buoyancy)
484 { 467 {
485 OMV.Vector3 ret = PhysicsScene.DefaultGravity; 468 OMV.Vector3 ret = PhysScene.DefaultGravity;
486 469
487 if (!IsStatic) 470 if (!IsStatic)
488 { 471 {
@@ -506,83 +489,121 @@ public class BSPrim : BSPhysObject
506 } 489 }
507 490
508 public override OMV.Vector3 Force { 491 public override OMV.Vector3 Force {
509 get { return _force; } 492 get { return RawForce; }
510 set { 493 set {
511 _force = value; 494 RawForce = value;
512 if (_force != OMV.Vector3.Zero) 495 EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate()
513 { 496 {
514 // If the force is non-zero, it must be reapplied each tick because 497 return new BSActorSetForce(PhysScene, this, SetForceActorName);
515 // Bullet clears the forces applied last frame. 498 });
516 RegisterPreStepAction("BSPrim.setForce", LocalID, 499 }
517 delegate(float timeStep) 500 }
518 {
519 if (!IsPhysicallyActive || _force == OMV.Vector3.Zero)
520 {
521 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
522 return;
523 }
524 501
525 DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force); 502 // Find and return a handle to the current vehicle actor.
526 if (PhysBody.HasPhysicalBody) 503 // Return 'null' if there is no vehicle actor.
527 { 504 public BSDynamics GetVehicleActor(bool createIfNone)
528 PhysicsScene.PE.ApplyCentralForce(PhysBody, _force); 505 {
529 ActivateIfPhysical(false); 506 BSDynamics ret = null;
530 } 507 BSActor actor;
531 } 508 if (PhysicalActors.TryGetActor(VehicleActorName, out actor))
532 ); 509 {
533 } 510 ret = actor as BSDynamics;
534 else 511 }
512 else
513 {
514 if (createIfNone)
535 { 515 {
536 UnRegisterPreStepAction("BSPrim.setForce", LocalID); 516 ret = new BSDynamics(PhysScene, this, VehicleActorName);
517 PhysicalActors.Add(ret.ActorName, ret);
537 } 518 }
538 } 519 }
520 return ret;
539 } 521 }
540 522
541 public override int VehicleType { 523 public override int VehicleType {
542 get { 524 get {
543 return (int)VehicleActor.Type; // if we are a vehicle, return that type 525 int ret = (int)Vehicle.TYPE_NONE;
526 BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */);
527 if (vehicleActor != null)
528 ret = (int)vehicleActor.Type;
529 return ret;
544 } 530 }
545 set { 531 set {
546 Vehicle type = (Vehicle)value; 532 Vehicle type = (Vehicle)value;
547 533
548 PhysicsScene.TaintedObject("setVehicleType", delegate() 534 PhysScene.TaintedObject(LocalID, "setVehicleType", delegate()
549 { 535 {
550 // Done at taint time so we're sure the physics engine is not using the variables 536 // Some vehicle scripts change vehicle type on the fly as an easy way to
551 // Vehicle code changes the parameters for this vehicle type. 537 // change all the parameters. Like a plane changing to CAR when on the
552 VehicleActor.ProcessTypeChange(type); 538 // ground. In this case, don't want to zero motion.
553 ActivateIfPhysical(false); 539 // ZeroMotion(true /* inTaintTime */);
540 if (type == Vehicle.TYPE_NONE)
541 {
542 // Vehicle type is 'none' so get rid of any actor that may have been allocated.
543 BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */);
544 if (vehicleActor != null)
545 {
546 PhysicalActors.RemoveAndRelease(vehicleActor.ActorName);
547 }
548 }
549 else
550 {
551 // Vehicle type is not 'none' so create an actor and set it running.
552 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
553 if (vehicleActor != null)
554 {
555 vehicleActor.ProcessTypeChange(type);
556 ActivateIfPhysical(false);
557 }
558 }
554 }); 559 });
555 } 560 }
556 } 561 }
557 public override void VehicleFloatParam(int param, float value) 562 public override void VehicleFloatParam(int param, float value)
558 { 563 {
559 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 564 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFloatParam", delegate()
560 { 565 {
561 VehicleActor.ProcessFloatVehicleParam((Vehicle)param, value); 566 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
562 ActivateIfPhysical(false); 567 if (vehicleActor != null)
568 {
569 vehicleActor.ProcessFloatVehicleParam((Vehicle)param, value);
570 ActivateIfPhysical(false);
571 }
563 }); 572 });
564 } 573 }
565 public override void VehicleVectorParam(int param, OMV.Vector3 value) 574 public override void VehicleVectorParam(int param, OMV.Vector3 value)
566 { 575 {
567 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 576 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleVectorParam", delegate()
568 { 577 {
569 VehicleActor.ProcessVectorVehicleParam((Vehicle)param, value); 578 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
570 ActivateIfPhysical(false); 579 if (vehicleActor != null)
580 {
581 vehicleActor.ProcessVectorVehicleParam((Vehicle)param, value);
582 ActivateIfPhysical(false);
583 }
571 }); 584 });
572 } 585 }
573 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 586 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
574 { 587 {
575 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 588 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleRotationParam", delegate()
576 { 589 {
577 VehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation); 590 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
578 ActivateIfPhysical(false); 591 if (vehicleActor != null)
592 {
593 vehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation);
594 ActivateIfPhysical(false);
595 }
579 }); 596 });
580 } 597 }
581 public override void VehicleFlags(int param, bool remove) 598 public override void VehicleFlags(int param, bool remove)
582 { 599 {
583 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() 600 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFlags", delegate()
584 { 601 {
585 VehicleActor.ProcessVehicleFlags(param, remove); 602 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
603 if (vehicleActor != null)
604 {
605 vehicleActor.ProcessVehicleFlags(param, remove);
606 }
586 }); 607 });
587 } 608 }
588 609
@@ -592,7 +613,7 @@ public class BSPrim : BSPhysObject
592 if (_isVolumeDetect != newValue) 613 if (_isVolumeDetect != newValue)
593 { 614 {
594 _isVolumeDetect = newValue; 615 _isVolumeDetect = newValue;
595 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() 616 PhysScene.TaintedObject(LocalID, "BSPrim.SetVolumeDetect", delegate()
596 { 617 {
597 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); 618 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
598 SetObjectDynamic(true); 619 SetObjectDynamic(true);
@@ -600,10 +621,14 @@ public class BSPrim : BSPhysObject
600 } 621 }
601 return; 622 return;
602 } 623 }
624 public override bool IsVolumeDetect
625 {
626 get { return _isVolumeDetect; }
627 }
603 public override void SetMaterial(int material) 628 public override void SetMaterial(int material)
604 { 629 {
605 base.SetMaterial(material); 630 base.SetMaterial(material);
606 PhysicsScene.TaintedObject("BSPrim.SetMaterial", delegate() 631 PhysScene.TaintedObject(LocalID, "BSPrim.SetMaterial", delegate()
607 { 632 {
608 UpdatePhysicalParameters(); 633 UpdatePhysicalParameters();
609 }); 634 });
@@ -616,7 +641,7 @@ public class BSPrim : BSPhysObject
616 if (base.Friction != value) 641 if (base.Friction != value)
617 { 642 {
618 base.Friction = value; 643 base.Friction = value;
619 PhysicsScene.TaintedObject("BSPrim.setFriction", delegate() 644 PhysScene.TaintedObject(LocalID, "BSPrim.setFriction", delegate()
620 { 645 {
621 UpdatePhysicalParameters(); 646 UpdatePhysicalParameters();
622 }); 647 });
@@ -631,7 +656,7 @@ public class BSPrim : BSPhysObject
631 if (base.Restitution != value) 656 if (base.Restitution != value)
632 { 657 {
633 base.Restitution = value; 658 base.Restitution = value;
634 PhysicsScene.TaintedObject("BSPrim.setRestitution", delegate() 659 PhysScene.TaintedObject(LocalID, "BSPrim.setRestitution", delegate()
635 { 660 {
636 UpdatePhysicalParameters(); 661 UpdatePhysicalParameters();
637 }); 662 });
@@ -648,7 +673,7 @@ public class BSPrim : BSPhysObject
648 if (base.Density != value) 673 if (base.Density != value)
649 { 674 {
650 base.Density = value; 675 base.Density = value;
651 PhysicsScene.TaintedObject("BSPrim.setDensity", delegate() 676 PhysScene.TaintedObject(LocalID, "BSPrim.setDensity", delegate()
652 { 677 {
653 UpdatePhysicalParameters(); 678 UpdatePhysicalParameters();
654 }); 679 });
@@ -663,93 +688,66 @@ public class BSPrim : BSPhysObject
663 if (base.GravModifier != value) 688 if (base.GravModifier != value)
664 { 689 {
665 base.GravModifier = value; 690 base.GravModifier = value;
666 PhysicsScene.TaintedObject("BSPrim.setGravityModifier", delegate() 691 PhysScene.TaintedObject(LocalID, "BSPrim.setGravityModifier", delegate()
667 { 692 {
668 UpdatePhysicalParameters(); 693 UpdatePhysicalParameters();
669 }); 694 });
670 } 695 }
671 } 696 }
672 } 697 }
673 public override OMV.Vector3 RawVelocity
674 {
675 get { return _velocity; }
676 set { _velocity = value; }
677 }
678 public override OMV.Vector3 Velocity { 698 public override OMV.Vector3 Velocity {
679 get { return _velocity; } 699 get { return RawVelocity; }
680 set { 700 set {
681 _velocity = value; 701 RawVelocity = value;
682 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 702 PhysScene.TaintedObject(LocalID, "BSPrim.setVelocity", delegate()
683 { 703 {
684 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 704 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
685 ForceVelocity = _velocity; 705 ForceVelocity = RawVelocity;
686 }); 706 });
687 } 707 }
688 } 708 }
689 public override OMV.Vector3 ForceVelocity { 709 public override OMV.Vector3 ForceVelocity {
690 get { return _velocity; } 710 get { return RawVelocity; }
691 set { 711 set {
692 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); 712 PhysScene.AssertInTaintTime("BSPrim.ForceVelocity");
693 713
694 _velocity = Util.ClampV(value, BSParam.MaxLinearVelocity); 714 RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
695 if (PhysBody.HasPhysicalBody) 715 if (PhysBody.HasPhysicalBody)
696 { 716 {
697 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity); 717 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity);
698 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); 718 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
699 ActivateIfPhysical(false); 719 ActivateIfPhysical(false);
700 } 720 }
701 } 721 }
702 } 722 }
703 public override OMV.Vector3 Torque { 723 public override OMV.Vector3 Torque {
704 get { return _torque; } 724 get { return RawTorque; }
705 set { 725 set {
706 _torque = value; 726 RawTorque = value;
707 if (_torque != OMV.Vector3.Zero) 727 EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate()
708 {
709 // If the torque is non-zero, it must be reapplied each tick because
710 // Bullet clears the forces applied last frame.
711 RegisterPreStepAction("BSPrim.setTorque", LocalID,
712 delegate(float timeStep)
713 {
714 if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero)
715 {
716 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
717 return;
718 }
719
720 if (PhysBody.HasPhysicalBody)
721 AddAngularForce(_torque, false, true);
722 }
723 );
724 }
725 else
726 { 728 {
727 UnRegisterPreStepAction("BSPrim.setTorque", LocalID); 729 return new BSActorSetTorque(PhysScene, this, SetTorqueActorName);
728 } 730 });
729 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 731 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque);
730 } 732 }
731 } 733 }
732 public override OMV.Vector3 Acceleration { 734 public override OMV.Vector3 Acceleration {
733 get { return _acceleration; } 735 get { return _acceleration; }
734 set { _acceleration = value; } 736 set { _acceleration = value; }
735 } 737 }
736 public override OMV.Quaternion RawOrientation 738
737 {
738 get { return _orientation; }
739 set { _orientation = value; }
740 }
741 public override OMV.Quaternion Orientation { 739 public override OMV.Quaternion Orientation {
742 get { 740 get {
743 return _orientation; 741 return RawOrientation;
744 } 742 }
745 set { 743 set {
746 if (_orientation == value) 744 if (RawOrientation == value)
747 return; 745 return;
748 _orientation = value; 746 RawOrientation = value;
749 747
750 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 748 PhysScene.TaintedObject(LocalID, "BSPrim.setOrientation", delegate()
751 { 749 {
752 ForceOrientation = _orientation; 750 ForceOrientation = RawOrientation;
753 }); 751 });
754 } 752 }
755 } 753 }
@@ -758,14 +756,14 @@ public class BSPrim : BSPhysObject
758 { 756 {
759 get 757 get
760 { 758 {
761 _orientation = PhysicsScene.PE.GetOrientation(PhysBody); 759 RawOrientation = PhysScene.PE.GetOrientation(PhysBody);
762 return _orientation; 760 return RawOrientation;
763 } 761 }
764 set 762 set
765 { 763 {
766 _orientation = value; 764 RawOrientation = value;
767 if (PhysBody.HasPhysicalBody) 765 if (PhysBody.HasPhysicalBody)
768 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 766 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
769 } 767 }
770 } 768 }
771 public override int PhysicsActorType { 769 public override int PhysicsActorType {
@@ -778,7 +776,7 @@ public class BSPrim : BSPhysObject
778 if (_isPhysical != value) 776 if (_isPhysical != value)
779 { 777 {
780 _isPhysical = value; 778 _isPhysical = value;
781 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() 779 PhysScene.TaintedObject(LocalID, "BSPrim.setIsPhysical", delegate()
782 { 780 {
783 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 781 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
784 SetObjectDynamic(true); 782 SetObjectDynamic(true);
@@ -822,24 +820,24 @@ public class BSPrim : BSPhysObject
822 // isSolid: other objects bounce off of this object 820 // isSolid: other objects bounce off of this object
823 // isVolumeDetect: other objects pass through but can generate collisions 821 // isVolumeDetect: other objects pass through but can generate collisions
824 // collisionEvents: whether this object returns collision events 822 // collisionEvents: whether this object returns collision events
823 // NOTE: overloaded by BSPrimLinkable to also update linkset physical parameters.
825 public virtual void UpdatePhysicalParameters() 824 public virtual void UpdatePhysicalParameters()
826 { 825 {
827 if (!PhysBody.HasPhysicalBody) 826 if (!PhysBody.HasPhysicalBody)
828 { 827 {
829 // This would only happen if updates are called for during initialization when the body is not set up yet. 828 // This would only happen if updates are called for during initialization when the body is not set up yet.
830 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); 829 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID);
831 return; 830 return;
832 } 831 }
833 832
834 // Mangling all the physical properties requires the object not be in the physical world. 833 // Mangling all the physical properties requires the object not be in the physical world.
835 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). 834 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
836 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 835 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
837 836
838 // Set up the object physicalness (does gravity and collisions move this object) 837 // Set up the object physicalness (does gravity and collisions move this object)
839 MakeDynamic(IsStatic); 838 MakeDynamic(IsStatic);
840 839
841 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) 840 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
842 VehicleActor.Refresh();
843 PhysicalActors.Refresh(); 841 PhysicalActors.Refresh();
844 842
845 // Arrange for collision events if the simulator wants them 843 // Arrange for collision events if the simulator wants them
@@ -851,10 +849,11 @@ public class BSPrim : BSPhysObject
851 AddObjectToPhysicalWorld(); 849 AddObjectToPhysicalWorld();
852 850
853 // Rebuild its shape 851 // Rebuild its shape
854 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); 852 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
855 853
856 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", 854 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
857 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); 855 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(),
856 CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
858 } 857 }
859 858
860 // "Making dynamic" means changing to and from static. 859 // "Making dynamic" means changing to and from static.
@@ -867,28 +866,28 @@ public class BSPrim : BSPhysObject
867 if (makeStatic) 866 if (makeStatic)
868 { 867 {
869 // Become a Bullet 'static' object type 868 // Become a Bullet 'static' object type
870 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 869 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
871 // Stop all movement 870 // Stop all movement
872 ZeroMotion(true); 871 ZeroMotion(true);
873 872
874 // Set various physical properties so other object interact properly 873 // Set various physical properties so other object interact properly
875 PhysicsScene.PE.SetFriction(PhysBody, Friction); 874 PhysScene.PE.SetFriction(PhysBody, Friction);
876 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 875 PhysScene.PE.SetRestitution(PhysBody, Restitution);
877 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 876 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
878 877
879 // Mass is zero which disables a bunch of physics stuff in Bullet 878 // Mass is zero which disables a bunch of physics stuff in Bullet
880 UpdatePhysicalMassProperties(0f, false); 879 UpdatePhysicalMassProperties(0f, false);
881 // Set collision detection parameters 880 // Set collision detection parameters
882 if (BSParam.CcdMotionThreshold > 0f) 881 if (BSParam.CcdMotionThreshold > 0f)
883 { 882 {
884 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 883 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
885 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 884 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
886 } 885 }
887 886
888 // The activation state is 'disabled' so Bullet will not try to act on it. 887 // The activation state is 'disabled' so Bullet will not try to act on it.
889 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); 888 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION);
890 // Start it out sleeping and physical actions could wake it up. 889 // Start it out sleeping and physical actions could wake it up.
891 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); 890 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING);
892 891
893 // This collides like a static object 892 // This collides like a static object
894 PhysBody.collisionType = CollisionType.Static; 893 PhysBody.collisionType = CollisionType.Static;
@@ -896,11 +895,11 @@ public class BSPrim : BSPhysObject
896 else 895 else
897 { 896 {
898 // Not a Bullet static object 897 // Not a Bullet static object
899 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 898 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
900 899
901 // Set various physical properties so other object interact properly 900 // Set various physical properties so other object interact properly
902 PhysicsScene.PE.SetFriction(PhysBody, Friction); 901 PhysScene.PE.SetFriction(PhysBody, Friction);
903 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 902 PhysScene.PE.SetRestitution(PhysBody, Restitution);
904 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution); 903 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution);
905 904
906 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 905 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
@@ -908,8 +907,8 @@ public class BSPrim : BSPhysObject
908 // PhysicsScene.PE.ClearAllForces(BSBody); 907 // PhysicsScene.PE.ClearAllForces(BSBody);
909 908
910 // For good measure, make sure the transform is set through to the motion state 909 // For good measure, make sure the transform is set through to the motion state
911 ForcePosition = _position; 910 ForcePosition = RawPosition;
912 ForceVelocity = _velocity; 911 ForceVelocity = RawVelocity;
913 ForceRotationalVelocity = _rotationalVelocity; 912 ForceRotationalVelocity = _rotationalVelocity;
914 913
915 // A dynamic object has mass 914 // A dynamic object has mass
@@ -918,22 +917,22 @@ public class BSPrim : BSPhysObject
918 // Set collision detection parameters 917 // Set collision detection parameters
919 if (BSParam.CcdMotionThreshold > 0f) 918 if (BSParam.CcdMotionThreshold > 0f)
920 { 919 {
921 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 920 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
922 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 921 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
923 } 922 }
924 923
925 // Various values for simulation limits 924 // Various values for simulation limits
926 PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); 925 PhysScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping);
927 PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); 926 PhysScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime);
928 PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); 927 PhysScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold);
929 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 928 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
930 929
931 // This collides like an object. 930 // This collides like an object.
932 PhysBody.collisionType = CollisionType.Dynamic; 931 PhysBody.collisionType = CollisionType.Dynamic;
933 932
934 // Force activation of the object so Bullet will act on it. 933 // Force activation of the object so Bullet will act on it.
935 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. 934 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
936 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); 935 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
937 } 936 }
938 } 937 }
939 938
@@ -943,7 +942,7 @@ public class BSPrim : BSPhysObject
943 // the functions after this one set up the state of a possibly newly created collision body. 942 // the functions after this one set up the state of a possibly newly created collision body.
944 private void MakeSolid(bool makeSolid) 943 private void MakeSolid(bool makeSolid)
945 { 944 {
946 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody); 945 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysScene.PE.GetBodyType(PhysBody);
947 if (makeSolid) 946 if (makeSolid)
948 { 947 {
949 // Verify the previous code created the correct shape for this type of thing. 948 // Verify the previous code created the correct shape for this type of thing.
@@ -951,7 +950,7 @@ public class BSPrim : BSPhysObject
951 { 950 {
952 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); 951 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
953 } 952 }
954 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 953 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
955 } 954 }
956 else 955 else
957 { 956 {
@@ -959,32 +958,23 @@ public class BSPrim : BSPhysObject
959 { 958 {
960 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 959 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
961 } 960 }
962 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 961 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
963 962
964 // Change collision info from a static object to a ghosty collision object 963 // Change collision info from a static object to a ghosty collision object
965 PhysBody.collisionType = CollisionType.VolumeDetect; 964 PhysBody.collisionType = CollisionType.VolumeDetect;
966 } 965 }
967 } 966 }
968 967
969 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
970 // they need waking up when parameters are changed.
971 // Called in taint-time!!
972 private void ActivateIfPhysical(bool forceIt)
973 {
974 if (IsPhysical && PhysBody.HasPhysicalBody)
975 PhysicsScene.PE.Activate(PhysBody, forceIt);
976 }
977
978 // Turn on or off the flag controlling whether collision events are returned to the simulator. 968 // Turn on or off the flag controlling whether collision events are returned to the simulator.
979 private void EnableCollisions(bool wantsCollisionEvents) 969 private void EnableCollisions(bool wantsCollisionEvents)
980 { 970 {
981 if (wantsCollisionEvents) 971 if (wantsCollisionEvents)
982 { 972 {
983 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 973 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
984 } 974 }
985 else 975 else
986 { 976 {
987 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 977 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
988 } 978 }
989 } 979 }
990 980
@@ -995,7 +985,7 @@ public class BSPrim : BSPhysObject
995 { 985 {
996 if (PhysBody.HasPhysicalBody) 986 if (PhysBody.HasPhysicalBody)
997 { 987 {
998 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 988 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
999 } 989 }
1000 else 990 else
1001 { 991 {
@@ -1030,12 +1020,12 @@ public class BSPrim : BSPhysObject
1030 public override bool FloatOnWater { 1020 public override bool FloatOnWater {
1031 set { 1021 set {
1032 _floatOnWater = value; 1022 _floatOnWater = value;
1033 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() 1023 PhysScene.TaintedObject(LocalID, "BSPrim.setFloatOnWater", delegate()
1034 { 1024 {
1035 if (_floatOnWater) 1025 if (_floatOnWater)
1036 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 1026 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
1037 else 1027 else
1038 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 1028 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
1039 }); 1029 });
1040 } 1030 }
1041 } 1031 }
@@ -1047,7 +1037,7 @@ public class BSPrim : BSPhysObject
1047 _rotationalVelocity = value; 1037 _rotationalVelocity = value;
1048 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); 1038 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity);
1049 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 1039 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
1050 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 1040 PhysScene.TaintedObject(LocalID, "BSPrim.setRotationalVelocity", delegate()
1051 { 1041 {
1052 ForceRotationalVelocity = _rotationalVelocity; 1042 ForceRotationalVelocity = _rotationalVelocity;
1053 }); 1043 });
@@ -1062,7 +1052,7 @@ public class BSPrim : BSPhysObject
1062 if (PhysBody.HasPhysicalBody) 1052 if (PhysBody.HasPhysicalBody)
1063 { 1053 {
1064 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 1054 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
1065 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 1055 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
1066 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 1056 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
1067 ActivateIfPhysical(false); 1057 ActivateIfPhysical(false);
1068 } 1058 }
@@ -1078,7 +1068,7 @@ public class BSPrim : BSPhysObject
1078 get { return _buoyancy; } 1068 get { return _buoyancy; }
1079 set { 1069 set {
1080 _buoyancy = value; 1070 _buoyancy = value;
1081 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() 1071 PhysScene.TaintedObject(LocalID, "BSPrim.setBuoyancy", delegate()
1082 { 1072 {
1083 ForceBuoyancy = _buoyancy; 1073 ForceBuoyancy = _buoyancy;
1084 }); 1074 });
@@ -1096,179 +1086,54 @@ public class BSPrim : BSPhysObject
1096 } 1086 }
1097 } 1087 }
1098 1088
1099 // Used for MoveTo
1100 public override OMV.Vector3 PIDTarget {
1101 set
1102 {
1103 // TODO: add a sanity check -- don't move more than a region or something like that.
1104 _PIDTarget = value;
1105 }
1106 }
1107 public override float PIDTau {
1108 set { _PIDTau = value; }
1109 }
1110 public override bool PIDActive { 1089 public override bool PIDActive {
1111 set { 1090 set {
1112 if (value) 1091 base.MoveToTargetActive = value;
1092 EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate()
1113 { 1093 {
1114 // We're taking over after this. 1094 return new BSActorMoveToTarget(PhysScene, this, MoveToTargetActorName);
1115 ZeroMotion(true); 1095 });
1116 1096 }
1117 _targetMotor = new BSVMotor("BSPrim.PIDTarget", 1097 }
1118 _PIDTau, // timeScale
1119 BSMotor.Infinite, // decay time scale
1120 BSMotor.InfiniteVector, // friction timescale
1121 1f // efficiency
1122 );
1123 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1124 _targetMotor.SetTarget(_PIDTarget);
1125 _targetMotor.SetCurrent(RawPosition);
1126 /*
1127 _targetMotor = new BSPIDVMotor("BSPrim.PIDTarget");
1128 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1129
1130 _targetMotor.SetTarget(_PIDTarget);
1131 _targetMotor.SetCurrent(RawPosition);
1132 _targetMotor.TimeScale = _PIDTau;
1133 _targetMotor.Efficiency = 1f;
1134 */
1135
1136 RegisterPreStepAction("BSPrim.PIDTarget", LocalID, delegate(float timeStep)
1137 {
1138 if (!IsPhysicallyActive)
1139 {
1140 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID);
1141 return;
1142 }
1143
1144 OMV.Vector3 origPosition = RawPosition; // DEBUG DEBUG (for printout below)
1145
1146 // 'movePosition' is where we'd like the prim to be at this moment.
1147 OMV.Vector3 movePosition = RawPosition + _targetMotor.Step(timeStep);
1148 1098
1149 // If we are very close to our target, turn off the movement motor. 1099 public override OMV.Vector3 PIDTarget
1150 if (_targetMotor.ErrorIsZero()) 1100 {
1151 { 1101 set
1152 DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}", 1102 {
1153 LocalID, movePosition, RawPosition, Mass); 1103 base.PIDTarget = value;
1154 ForcePosition = _targetMotor.TargetValue; 1104 BSActor actor;
1155 _targetMotor.Enabled = false; 1105 if (PhysicalActors.TryGetActor(MoveToTargetActorName, out actor))
1156 }
1157 else
1158 {
1159 _position = movePosition;
1160 PositionSanityCheck(true /* intaintTime */);
1161 ForcePosition = _position;
1162 }
1163 DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
1164 });
1165 }
1166 else
1167 { 1106 {
1168 // Stop any targetting 1107 // if the actor exists, tell it to refresh its values.
1169 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); 1108 actor.Refresh();
1170 } 1109 }
1110
1171 } 1111 }
1172 } 1112 }
1173
1174 // Used for llSetHoverHeight and maybe vehicle height 1113 // Used for llSetHoverHeight and maybe vehicle height
1175 // Hover Height will override MoveTo target's Z 1114 // Hover Height will override MoveTo target's Z
1176 public override bool PIDHoverActive { 1115 public override bool PIDHoverActive {
1177 set { 1116 set {
1178 if (value) 1117 base.HoverActive = value;
1118 EnableActor(HoverActive, HoverActorName, delegate()
1179 { 1119 {
1180 // Turning the target on 1120 return new BSActorHover(PhysScene, this, HoverActorName);
1181 _hoverMotor = new BSFMotor("BSPrim.Hover", 1121 });
1182 _PIDHoverTau, // timeScale
1183 BSMotor.Infinite, // decay time scale
1184 BSMotor.Infinite, // friction timescale
1185 1f // efficiency
1186 );
1187 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1188 _hoverMotor.SetCurrent(RawPosition.Z);
1189 _hoverMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1190
1191 RegisterPreStepAction("BSPrim.Hover", LocalID, delegate(float timeStep)
1192 {
1193 // Don't do hovering while the object is selected.
1194 if (!IsPhysicallyActive)
1195 return;
1196
1197 _hoverMotor.SetCurrent(RawPosition.Z);
1198 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1199 float targetHeight = _hoverMotor.Step(timeStep);
1200
1201 // 'targetHeight' is where we'd like the Z of the prim to be at this moment.
1202 // Compute the amount of force to push us there.
1203 float moveForce = (targetHeight - RawPosition.Z) * Mass;
1204 // Undo anything the object thinks it's doing at the moment
1205 moveForce = -RawVelocity.Z * Mass;
1206
1207 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, new OMV.Vector3(0f, 0f, moveForce));
1208 DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", LocalID, targetHeight, moveForce, Mass);
1209 });
1210 }
1211 else
1212 {
1213 UnRegisterPreStepAction("BSPrim.Hover", LocalID);
1214 }
1215 }
1216 }
1217 public override float PIDHoverHeight {
1218 set { _PIDHoverHeight = value; }
1219 }
1220 public override PIDHoverType PIDHoverType {
1221 set { _PIDHoverType = value; }
1222 }
1223 public override float PIDHoverTau {
1224 set { _PIDHoverTau = value; }
1225 }
1226 // Based on current position, determine what we should be hovering at now.
1227 // Must recompute often. What if we walked offa cliff>
1228 private float ComputeCurrentPIDHoverHeight()
1229 {
1230 float ret = _PIDHoverHeight;
1231 float groundHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
1232
1233 switch (_PIDHoverType)
1234 {
1235 case PIDHoverType.Ground:
1236 ret = groundHeight + _PIDHoverHeight;
1237 break;
1238 case PIDHoverType.GroundAndWater:
1239 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
1240 if (groundHeight > waterHeight)
1241 {
1242 ret = groundHeight + _PIDHoverHeight;
1243 }
1244 else
1245 {
1246 ret = waterHeight + _PIDHoverHeight;
1247 }
1248 break;
1249 } 1122 }
1250 return ret;
1251 } 1123 }
1252 1124
1253
1254 // For RotLookAt
1255 public override OMV.Quaternion APIDTarget { set { return; } }
1256 public override bool APIDActive { set { return; } }
1257 public override float APIDStrength { set { return; } }
1258 public override float APIDDamping { set { return; } }
1259
1260 public override void AddForce(OMV.Vector3 force, bool pushforce) { 1125 public override void AddForce(OMV.Vector3 force, bool pushforce) {
1261 // Per documentation, max force is limited. 1126 // Per documentation, max force is limited.
1262 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 1127 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
1263 1128
1264 // Since this force is being applied in only one step, make this a force per second. 1129 // Since this force is being applied in only one step, make this a force per second.
1265 addForce /= PhysicsScene.LastTimeStep; 1130 addForce /= PhysScene.LastTimeStep;
1266 AddForce(addForce, pushforce, false /* inTaintTime */); 1131 AddForce(addForce, pushforce, false /* inTaintTime */);
1267 } 1132 }
1268 1133
1269 // Applying a force just adds this to the total force on the object. 1134 // Applying a force just adds this to the total force on the object.
1270 // This added force will only last the next simulation tick. 1135 // This added force will only last the next simulation tick.
1271 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 1136 public override void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
1272 // for an object, doesn't matter if force is a pushforce or not 1137 // for an object, doesn't matter if force is a pushforce or not
1273 if (IsPhysicallyActive) 1138 if (IsPhysicallyActive)
1274 { 1139 {
@@ -1277,13 +1142,15 @@ public class BSPrim : BSPhysObject
1277 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); 1142 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
1278 1143
1279 OMV.Vector3 addForce = force; 1144 OMV.Vector3 addForce = force;
1280 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() 1145 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddForce", delegate()
1281 { 1146 {
1282 // Bullet adds this central force to the total force for this tick 1147 // Bullet adds this central force to the total force for this tick.
1148 // Deep down in Bullet:
1149 // linearVelocity += totalForce / mass * timeStep;
1283 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); 1150 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1284 if (PhysBody.HasPhysicalBody) 1151 if (PhysBody.HasPhysicalBody)
1285 { 1152 {
1286 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 1153 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
1287 ActivateIfPhysical(false); 1154 ActivateIfPhysical(false);
1288 } 1155 }
1289 }); 1156 });
@@ -1305,13 +1172,13 @@ public class BSPrim : BSPhysObject
1305 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); 1172 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude);
1306 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); 1173 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
1307 1174
1308 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate() 1175 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddImpulse", delegate()
1309 { 1176 {
1310 // Bullet adds this impulse immediately to the velocity 1177 // Bullet adds this impulse immediately to the velocity
1311 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); 1178 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
1312 if (PhysBody.HasPhysicalBody) 1179 if (PhysBody.HasPhysicalBody)
1313 { 1180 {
1314 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse); 1181 PhysScene.PE.ApplyCentralImpulse(PhysBody, addImpulse);
1315 ActivateIfPhysical(false); 1182 ActivateIfPhysical(false);
1316 } 1183 }
1317 }); 1184 });
@@ -1324,20 +1191,18 @@ public class BSPrim : BSPhysObject
1324 } 1191 }
1325 } 1192 }
1326 1193
1327 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 1194 // BSPhysObject.AddAngularForce()
1328 AddAngularForce(force, pushforce, false); 1195 public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1329 }
1330 public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1331 { 1196 {
1332 if (force.IsFinite()) 1197 if (force.IsFinite())
1333 { 1198 {
1334 OMV.Vector3 angForce = force; 1199 OMV.Vector3 angForce = force;
1335 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() 1200 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddAngularForce", delegate()
1336 { 1201 {
1337 if (PhysBody.HasPhysicalBody) 1202 if (PhysBody.HasPhysicalBody)
1338 { 1203 {
1339 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce); 1204 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce);
1340 PhysicsScene.PE.ApplyTorque(PhysBody, angForce); 1205 PhysScene.PE.ApplyTorque(PhysBody, angForce);
1341 ActivateIfPhysical(false); 1206 ActivateIfPhysical(false);
1342 } 1207 }
1343 }); 1208 });
@@ -1356,11 +1221,11 @@ public class BSPrim : BSPhysObject
1356 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 1221 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1357 { 1222 {
1358 OMV.Vector3 applyImpulse = impulse; 1223 OMV.Vector3 applyImpulse = impulse;
1359 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() 1224 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ApplyTorqueImpulse", delegate()
1360 { 1225 {
1361 if (PhysBody.HasPhysicalBody) 1226 if (PhysBody.HasPhysicalBody)
1362 { 1227 {
1363 PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); 1228 PhysScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse);
1364 ActivateIfPhysical(false); 1229 ActivateIfPhysical(false);
1365 } 1230 }
1366 }); 1231 });
@@ -1649,6 +1514,8 @@ public class BSPrim : BSPhysObject
1649 1514
1650 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); 1515 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass);
1651 // DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass); 1516 // DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass);
1517 DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3},pathB={4},pathE={5},profB={6},profE={7},siz={8}",
1518 LocalID, Density, volume, returnMass, pathBegin, pathEnd, profileBegin, profileEnd, _size);
1652 1519
1653 return returnMass; 1520 return returnMass;
1654 }// end CalculateMass 1521 }// end CalculateMass
@@ -1661,13 +1528,14 @@ public class BSPrim : BSPhysObject
1661 { 1528 {
1662 // Create the correct physical representation for this type of object. 1529 // Create the correct physical representation for this type of object.
1663 // Updates base.PhysBody and base.PhysShape with the new information. 1530 // Updates base.PhysBody and base.PhysShape with the new information.
1664 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. 1531 // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary.
1665 PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) 1532 PhysScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysScene.World, this, delegate(BulletBody pBody, BulletShape pShape)
1666 { 1533 {
1667 // Called if the current prim body is about to be destroyed. 1534 // Called if the current prim body is about to be destroyed.
1668 // Remove all the physical dependencies on the old body. 1535 // Remove all the physical dependencies on the old body.
1669 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) 1536 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
1670 RemoveBodyDependencies(); 1537 // Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints.
1538 RemoveDependencies();
1671 }); 1539 });
1672 1540
1673 // Make sure the properties are set on the new object 1541 // Make sure the properties are set on the new object
@@ -1675,27 +1543,45 @@ public class BSPrim : BSPhysObject
1675 return; 1543 return;
1676 } 1544 }
1677 1545
1678 protected virtual void RemoveBodyDependencies() 1546 // Called at taint-time
1547 protected virtual void RemoveDependencies()
1548 {
1549 PhysicalActors.RemoveDependencies();
1550 }
1551
1552 #region Extension
1553 public override object Extension(string pFunct, params object[] pParams)
1679 { 1554 {
1680 VehicleActor.RemoveBodyDependencies(); 1555 DetailLog("{0} BSPrim.Extension,op={1}", LocalID, pFunct);
1681 PhysicalActors.RemoveBodyDependencies(); 1556 object ret = null;
1557 switch (pFunct)
1558 {
1559 default:
1560 ret = base.Extension(pFunct, pParams);
1561 break;
1562 }
1563 return ret;
1682 } 1564 }
1565 #endregion // Extension
1683 1566
1684 // The physics engine says that properties have updated. Update same and inform 1567 // The physics engine says that properties have updated. Update same and inform
1685 // the world that things have changed. 1568 // the world that things have changed.
1569 // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims.
1570 // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimDisplaced which handles mapping physical position to simulator position.
1686 public override void UpdateProperties(EntityProperties entprop) 1571 public override void UpdateProperties(EntityProperties entprop)
1687 { 1572 {
1573 // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
1688 TriggerPreUpdatePropertyAction(ref entprop); 1574 TriggerPreUpdatePropertyAction(ref entprop);
1689 1575
1690 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG 1576 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
1691 1577
1692 // Assign directly to the local variables so the normal set actions do not happen 1578 // Assign directly to the local variables so the normal set actions do not happen
1693 _position = entprop.Position; 1579 RawPosition = entprop.Position;
1694 _orientation = entprop.Rotation; 1580 RawOrientation = entprop.Rotation;
1695 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be 1581 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
1696 // very sensitive to velocity changes. 1582 // very sensitive to velocity changes.
1697 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, BSParam.UpdateVelocityChangeThreshold)) 1583 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold))
1698 _velocity = entprop.Velocity; 1584 RawVelocity = entprop.Velocity;
1699 _acceleration = entprop.Acceleration; 1585 _acceleration = entprop.Acceleration;
1700 _rotationalVelocity = entprop.RotationalVelocity; 1586 _rotationalVelocity = entprop.RotationalVelocity;
1701 1587
@@ -1704,29 +1590,20 @@ public class BSPrim : BSPhysObject
1704 // The sanity check can change the velocity and/or position. 1590 // The sanity check can change the velocity and/or position.
1705 if (PositionSanityCheck(true /* inTaintTime */ )) 1591 if (PositionSanityCheck(true /* inTaintTime */ ))
1706 { 1592 {
1707 entprop.Position = _position; 1593 entprop.Position = RawPosition;
1708 entprop.Velocity = _velocity; 1594 entprop.Velocity = RawVelocity;
1709 entprop.RotationalVelocity = _rotationalVelocity; 1595 entprop.RotationalVelocity = _rotationalVelocity;
1710 entprop.Acceleration = _acceleration; 1596 entprop.Acceleration = _acceleration;
1711 } 1597 }
1712 1598
1713 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG 1599 OMV.Vector3 direction = OMV.Vector3.UnitX * RawOrientation; // DEBUG DEBUG DEBUG
1714 DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction); 1600 DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction);
1715 1601
1716 // remember the current and last set values 1602 // remember the current and last set values
1717 LastEntityProperties = CurrentEntityProperties; 1603 LastEntityProperties = CurrentEntityProperties;
1718 CurrentEntityProperties = entprop; 1604 CurrentEntityProperties = entprop;
1719 1605
1720 base.RequestPhysicsterseUpdate(); 1606 PhysScene.PostUpdate(this);
1721 /*
1722 else
1723 {
1724 // For debugging, report the movement of children
1725 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1726 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1727 entprop.Acceleration, entprop.RotationalVelocity);
1728 }
1729 */
1730 } 1607 }
1731} 1608}
1732} 1609}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
index f1c3b5c..2eb1440 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
@@ -23,11 +23,6 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial
28 * are Copyright (c) 2009 Linden Research, Inc and are used under their license
29 * of Creative Commons Attribution-Share Alike 3.0
30 * (http://creativecommons.org/licenses/by-sa/3.0/).
31 */ 26 */
32 27
33using System; 28using System;
@@ -44,14 +39,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
44{ 39{
45public class BSPrimDisplaced : BSPrim 40public class BSPrimDisplaced : BSPrim
46{ 41{
47 // The purpose of this module is to do any mapping between what the simulator thinks 42 // The purpose of this subclass is to do any mapping between what the simulator thinks
48 // the prim position and orientation is and what the physical position/orientation. 43 // the prim position and orientation is and what the physical position/orientation.
49 // This difference happens because Bullet assumes the center-of-mass is the <0,0,0> 44 // This difference happens because Bullet assumes the center-of-mass is the <0,0,0>
50 // of the prim/linkset. The simulator tracks the location of the prim/linkset by 45 // of the prim/linkset. The simulator, on the other hand, tracks the location of
51 // the location of the root prim. So, if center-of-mass is anywhere but the origin 46 // the prim/linkset by the location of the root prim. So, if center-of-mass is anywhere
52 // of the root prim, the physical origin is displaced from the simulator origin. 47 // but the origin of the root prim, the physical origin is displaced from the simulator origin.
53 // 48 //
54 // This routine works by capturing the Force* setting of position/orientation/... and 49 // This routine works by capturing ForcePosition and
55 // adjusting the simulator values (being set) into the physical values. 50 // adjusting the simulator values (being set) into the physical values.
56 // The conversion is also done in the opposite direction (physical origin -> simulator origin). 51 // The conversion is also done in the opposite direction (physical origin -> simulator origin).
57 // 52 //
@@ -59,8 +54,8 @@ public class BSPrimDisplaced : BSPrim
59 // are converted into simulator origin values before being passed to the base 54 // are converted into simulator origin values before being passed to the base
60 // class. 55 // class.
61 56
57 // PositionDisplacement is the vehicle relative distance from the root prim position to the center-of-mass.
62 public virtual OMV.Vector3 PositionDisplacement { get; set; } 58 public virtual OMV.Vector3 PositionDisplacement { get; set; }
63 public virtual OMV.Quaternion OrientationDisplacement { get; set; }
64 59
65 public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 60 public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
66 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 61 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
@@ -69,68 +64,96 @@ public class BSPrimDisplaced : BSPrim
69 ClearDisplacement(); 64 ClearDisplacement();
70 } 65 }
71 66
67 // Clears any center-of-mass displacement introduced by linksets, etc.
68 // Does not clear the displacement set by the user.
72 public void ClearDisplacement() 69 public void ClearDisplacement()
73 { 70 {
74 PositionDisplacement = OMV.Vector3.Zero; 71 if (UserSetCenterOfMassDisplacement.HasValue)
75 OrientationDisplacement = OMV.Quaternion.Identity; 72 PositionDisplacement = (OMV.Vector3)UserSetCenterOfMassDisplacement;
73 else
74 PositionDisplacement = OMV.Vector3.Zero;
76 } 75 }
77 76
78 // Set this sets and computes the displacement from the passed prim to the center-of-mass. 77 // Set this sets and computes the displacement from the passed prim to the center-of-mass.
79 // A user set value for center-of-mass overrides whatever might be passed in here. 78 // A user set value for center-of-mass overrides whatever might be passed in here.
80 // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates). 79 // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates).
81 public virtual void SetEffectiveCenterOfMassW(Vector3 centerOfMassDisplacement) 80 // Returns the relative offset from the root position to the center-of-mass.
81 // Called at taint time.
82 public virtual Vector3 SetEffectiveCenterOfMassDisplacement(Vector3 centerOfMassDisplacement)
82 { 83 {
84 PhysScene.AssertInTaintTime("BSPrimDisplaced.SetEffectiveCenterOfMassDisplacement");
83 Vector3 comDisp; 85 Vector3 comDisp;
84 if (UserSetCenterOfMass.HasValue) 86 if (UserSetCenterOfMassDisplacement.HasValue)
85 comDisp = (OMV.Vector3)UserSetCenterOfMass; 87 comDisp = (OMV.Vector3)UserSetCenterOfMassDisplacement;
86 else 88 else
87 comDisp = centerOfMassDisplacement; 89 comDisp = centerOfMassDisplacement;
88 90
89 if (comDisp == Vector3.Zero) 91 // Eliminate any jitter caused be very slight differences in masses and positions
90 { 92 if (comDisp.ApproxEquals(Vector3.Zero, 0.01f) )
91 // If there is no diplacement. Things get reset. 93 comDisp = Vector3.Zero;
92 PositionDisplacement = OMV.Vector3.Zero; 94
93 OrientationDisplacement = OMV.Quaternion.Identity; 95 DetailLog("{0},BSPrimDisplaced.SetEffectiveCenterOfMassDisplacement,userSet={1},comDisp={2}",
94 } 96 LocalID, UserSetCenterOfMassDisplacement.HasValue, comDisp);
95 else 97 if ( !comDisp.ApproxEquals(PositionDisplacement, 0.01f) )
96 { 98 {
97 // Remember the displacement from root as well as the origional rotation of the 99 // Displacement setting is changing.
98 // new center-of-mass. 100 // The relationship between the physical object and simulated object must be aligned.
99 PositionDisplacement = comDisp; 101 PositionDisplacement = comDisp;
100 OrientationDisplacement = OMV.Quaternion.Identity; 102 this.ForcePosition = RawPosition;
101 } 103 }
104
105 return PositionDisplacement;
102 } 106 }
103 107
108 // 'ForcePosition' is the one way to set the physical position of the body in the physics engine.
109 // Displace the simulator idea of position (center of root prim) to the physical position.
104 public override Vector3 ForcePosition 110 public override Vector3 ForcePosition
105 { 111 {
106 get { return base.ForcePosition; } 112 get {
113 OMV.Vector3 physPosition = PhysScene.PE.GetPosition(PhysBody);
114 if (PositionDisplacement != OMV.Vector3.Zero)
115 {
116 // If there is some displacement, return the physical position (center-of-mass)
117 // location minus the displacement to give the center of the root prim.
118 OMV.Vector3 displacement = PositionDisplacement * ForceOrientation;
119 DetailLog("{0},BSPrimDisplaced.ForcePosition,get,physPos={1},disp={2},simPos={3}",
120 LocalID, physPosition, displacement, physPosition - displacement);
121 physPosition -= displacement;
122 }
123 RawPosition = physPosition;
124 return physPosition;
125 }
107 set 126 set
108 { 127 {
109 if (PositionDisplacement != OMV.Vector3.Zero) 128 if (PositionDisplacement != OMV.Vector3.Zero)
110 base.ForcePosition = value - (PositionDisplacement * RawOrientation); 129 {
130 // This value is the simulator's idea of where the prim is: the center of the root prim
131 RawPosition = value;
132
133 // Move the passed root prim postion to the center-of-mass position and set in the physics engine.
134 OMV.Vector3 displacement = PositionDisplacement * RawOrientation;
135 OMV.Vector3 displacedPos = RawPosition + displacement;
136 DetailLog("{0},BSPrimDisplaced.ForcePosition,set,simPos={1},disp={2},physPos={3}",
137 LocalID, RawPosition, displacement, displacedPos);
138 if (PhysBody.HasPhysicalBody)
139 {
140 PhysScene.PE.SetTranslation(PhysBody, displacedPos, RawOrientation);
141 ActivateIfPhysical(false);
142 }
143 }
111 else 144 else
145 {
112 base.ForcePosition = value; 146 base.ForcePosition = value;
147 }
113 } 148 }
114 } 149 }
115 150
116 public override Quaternion ForceOrientation 151 // These are also overridden by BSPrimLinkable if the prim can be part of a linkset
117 {
118 get { return base.ForceOrientation; }
119 set
120 {
121 base.ForceOrientation = value;
122 }
123 }
124
125 // TODO: decide if this is the right place for these variables.
126 // Somehow incorporate the optional settability by the user.
127 // Is this used?
128 public override OMV.Vector3 CenterOfMass 152 public override OMV.Vector3 CenterOfMass
129 { 153 {
130 get { return RawPosition; } 154 get { return RawPosition; }
131 } 155 }
132 156
133 // Is this used?
134 public override OMV.Vector3 GeometricCenter 157 public override OMV.Vector3 GeometricCenter
135 { 158 {
136 get { return RawPosition; } 159 get { return RawPosition; }
@@ -139,12 +162,18 @@ public class BSPrimDisplaced : BSPrim
139 public override void UpdateProperties(EntityProperties entprop) 162 public override void UpdateProperties(EntityProperties entprop)
140 { 163 {
141 // Undo any center-of-mass displacement that might have been done. 164 // Undo any center-of-mass displacement that might have been done.
142 if (PositionDisplacement != OMV.Vector3.Zero || OrientationDisplacement != OMV.Quaternion.Identity) 165 if (PositionDisplacement != OMV.Vector3.Zero)
143 { 166 {
144 // Correct for any rotation around the center-of-mass 167 // The origional shape was offset from 'zero' by PositionDisplacement.
145 // TODO!!! 168 // These physical location must be back converted to be centered around the displaced
146 entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation); 169 // root shape.
147 // entprop.Rotation = something; 170
171 // Move the returned center-of-mass location to the root prim location.
172 OMV.Vector3 displacement = PositionDisplacement * entprop.Rotation;
173 OMV.Vector3 displacedPos = entprop.Position - displacement;
174 DetailLog("{0},BSPrimDisplaced.UpdateProperties,physPos={1},disp={2},simPos={3}",
175 LocalID, entprop.Position, displacement, displacedPos);
176 entprop.Position = displacedPos;
148 } 177 }
149 178
150 base.UpdateProperties(entprop); 179 base.UpdateProperties(entprop);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
index d65d407..126b146 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
@@ -30,6 +30,7 @@ using System.Linq;
30using System.Text; 30using System.Text;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.OptionalModules.Scripting;
33 34
34using OMV = OpenMetaverse; 35using OMV = OpenMetaverse;
35 36
@@ -37,44 +38,49 @@ namespace OpenSim.Region.Physics.BulletSPlugin
37{ 38{
38public class BSPrimLinkable : BSPrimDisplaced 39public class BSPrimLinkable : BSPrimDisplaced
39{ 40{
41 // The purpose of this subclass is to add linkset functionality to the prim. This overrides
42 // operations necessary for keeping the linkset created and, additionally, this
43 // calls the linkset implementation for its creation and management.
44
45 private static readonly string LogHeader = "[BULLETS PRIMLINKABLE]";
46
47 // This adds the overrides for link() and delink() so the prim is linkable.
48
40 public BSLinkset Linkset { get; set; } 49 public BSLinkset Linkset { get; set; }
41 // The index of this child prim. 50 // The index of this child prim.
42 public int LinksetChildIndex { get; set; } 51 public int LinksetChildIndex { get; set; }
43 52
44 public BSLinksetInfo LinksetInfo { get; set; } 53 public BSLinkset.LinksetImplementation LinksetType { get; set; }
45 54
46 public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 55 public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
47 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 56 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
48 : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical) 57 : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
49 { 58 {
50 Linkset = BSLinkset.Factory(PhysicsScene, this); 59 // Default linkset implementation for this prim
60 LinksetType = (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation;
51 61
52 PhysicsScene.TaintedObject("BSPrimLinksetCompound.Refresh", delegate() 62 Linkset = BSLinkset.Factory(PhysScene, this);
53 { 63
54 Linkset.Refresh(this); 64 Linkset.Refresh(this);
55 });
56 } 65 }
57 66
58 public override void Destroy() 67 public override void Destroy()
59 { 68 {
60 Linkset = Linkset.RemoveMeFromLinkset(this); 69 Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime */);
61 base.Destroy(); 70 base.Destroy();
62 } 71 }
63 72
64 public override BSPhysicsShapeType PreferredPhysicalShape
65 { get { return Linkset.PreferredPhysicalShape(this); } }
66
67 public override void link(Manager.PhysicsActor obj) 73 public override void link(Manager.PhysicsActor obj)
68 { 74 {
69 BSPrimLinkable parent = obj as BSPrimLinkable; 75 BSPrimLinkable parent = obj as BSPrimLinkable;
70 if (parent != null) 76 if (parent != null)
71 { 77 {
72 BSPhysObject parentBefore = Linkset.LinksetRoot; 78 BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG
73 int childrenBefore = Linkset.NumberOfChildren; 79 int childrenBefore = Linkset.NumberOfChildren; // DEBUG
74 80
75 Linkset = parent.Linkset.AddMeToLinkset(this); 81 Linkset = parent.Linkset.AddMeToLinkset(this);
76 82
77 DetailLog("{0},BSPrimLinkset.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 83 DetailLog("{0},BSPrimLinkable.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
78 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); 84 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
79 } 85 }
80 return; 86 return;
@@ -85,12 +91,12 @@ public class BSPrimLinkable : BSPrimDisplaced
85 // TODO: decide if this parent checking needs to happen at taint time 91 // TODO: decide if this parent checking needs to happen at taint time
86 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 92 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
87 93
88 BSPhysObject parentBefore = Linkset.LinksetRoot; 94 BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG
89 int childrenBefore = Linkset.NumberOfChildren; 95 int childrenBefore = Linkset.NumberOfChildren; // DEBUG
90 96
91 Linkset = Linkset.RemoveMeFromLinkset(this); 97 Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime*/);
92 98
93 DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 99 DetailLog("{0},BSPrimLinkable.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
94 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); 100 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
95 return; 101 return;
96 } 102 }
@@ -102,7 +108,7 @@ public class BSPrimLinkable : BSPrimDisplaced
102 set 108 set
103 { 109 {
104 base.Position = value; 110 base.Position = value;
105 PhysicsScene.TaintedObject("BSPrimLinkset.setPosition", delegate() 111 PhysScene.TaintedObject(LocalID, "BSPrimLinkable.setPosition", delegate()
106 { 112 {
107 Linkset.UpdateProperties(UpdatedProperties.Position, this); 113 Linkset.UpdateProperties(UpdatedProperties.Position, this);
108 }); 114 });
@@ -116,7 +122,7 @@ public class BSPrimLinkable : BSPrimDisplaced
116 set 122 set
117 { 123 {
118 base.Orientation = value; 124 base.Orientation = value;
119 PhysicsScene.TaintedObject("BSPrimLinkset.setOrientation", delegate() 125 PhysScene.TaintedObject(LocalID, "BSPrimLinkable.setOrientation", delegate()
120 { 126 {
121 Linkset.UpdateProperties(UpdatedProperties.Orientation, this); 127 Linkset.UpdateProperties(UpdatedProperties.Orientation, this);
122 }); 128 });
@@ -128,6 +134,17 @@ public class BSPrimLinkable : BSPrimDisplaced
128 get { return Linkset.LinksetMass; } 134 get { return Linkset.LinksetMass; }
129 } 135 }
130 136
137 public override OMV.Vector3 CenterOfMass
138 {
139 get { return Linkset.CenterOfMass; }
140 }
141
142 public override OMV.Vector3 GeometricCenter
143 {
144 get { return Linkset.GeometricCenter; }
145 }
146
147 // Refresh the linkset structure and parameters when the prim's physical parameters are changed.
131 public override void UpdatePhysicalParameters() 148 public override void UpdatePhysicalParameters()
132 { 149 {
133 base.UpdatePhysicalParameters(); 150 base.UpdatePhysicalParameters();
@@ -139,44 +156,193 @@ public class BSPrimLinkable : BSPrimDisplaced
139 Linkset.Refresh(this); 156 Linkset.Refresh(this);
140 } 157 }
141 158
159 // When the prim is made dynamic or static, the linkset needs to change.
142 protected override void MakeDynamic(bool makeStatic) 160 protected override void MakeDynamic(bool makeStatic)
143 { 161 {
144 base.MakeDynamic(makeStatic); 162 base.MakeDynamic(makeStatic);
145 if (makeStatic) 163 if (Linkset != null) // null can happen during initialization
146 Linkset.MakeStatic(this); 164 {
147 else 165 if (makeStatic)
148 Linkset.MakeDynamic(this); 166 Linkset.MakeStatic(this);
167 else
168 Linkset.MakeDynamic(this);
169 }
149 } 170 }
150 171
151 // Body is being taken apart. Remove physical dependencies and schedule a rebuild. 172 // Body is being taken apart. Remove physical dependencies and schedule a rebuild.
152 protected override void RemoveBodyDependencies() 173 protected override void RemoveDependencies()
153 { 174 {
154 Linkset.RemoveBodyDependencies(this); 175 Linkset.RemoveDependencies(this);
155 base.RemoveBodyDependencies(); 176 base.RemoveDependencies();
156 } 177 }
157 178
179 // Called after a simulation step for the changes in physical object properties.
180 // Do any filtering/modification needed for linksets.
158 public override void UpdateProperties(EntityProperties entprop) 181 public override void UpdateProperties(EntityProperties entprop)
159 { 182 {
160 if (Linkset.IsRoot(this)) 183 if (Linkset.IsRoot(this) || Linkset.ShouldReportPropertyUpdates(this))
161 { 184 {
162 // Properties are only updated for the roots of a linkset. 185 // Properties are only updated for the roots of a linkset.
163 // TODO: this will have to change when linksets are articulated. 186 // TODO: this will have to change when linksets are articulated.
164 base.UpdateProperties(entprop); 187 base.UpdateProperties(entprop);
165 } 188 }
189 /*
190 else
191 {
192 // For debugging, report the movement of children
193 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
194 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
195 entprop.Acceleration, entprop.RotationalVelocity);
196 }
197 */
166 // The linkset might like to know about changing locations 198 // The linkset might like to know about changing locations
167 Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); 199 Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
168 } 200 }
169 201
202 // Called after a simulation step to post a collision with this object.
203 // This returns 'true' if the collision has been queued and the SendCollisions call must
204 // be made at the end of the simulation step.
170 public override bool Collide(uint collidingWith, BSPhysObject collidee, 205 public override bool Collide(uint collidingWith, BSPhysObject collidee,
171 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 206 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
172 { 207 {
173 // prims in the same linkset cannot collide with each other 208 bool ret = false;
174 BSPrimLinkable convCollidee = collidee as BSPrimLinkable; 209 // Ask the linkset if it wants to handle the collision
175 if (convCollidee != null && (this.Linkset.LinksetID == convCollidee.Linkset.LinksetID)) 210 if (!Linkset.HandleCollide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth))
211 {
212 // The linkset didn't handle it so pass the collision through normal processing
213 ret = base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth);
214 }
215 return ret;
216 }
217
218 // A linkset reports any collision on any part of the linkset.
219 public long SomeCollisionSimulationStep = 0;
220 public override bool HasSomeCollision
221 {
222 get
223 {
224 return (SomeCollisionSimulationStep == PhysScene.SimulationStep) || base.IsColliding;
225 }
226 set
176 { 227 {
177 return false; 228 if (value)
229 SomeCollisionSimulationStep = PhysScene.SimulationStep;
230 else
231 SomeCollisionSimulationStep = 0;
232
233 base.HasSomeCollision = value;
234 }
235 }
236
237 // Convert the existing linkset of this prim into a new type.
238 public bool ConvertLinkset(BSLinkset.LinksetImplementation newType)
239 {
240 bool ret = false;
241 if (LinksetType != newType)
242 {
243 DetailLog("{0},BSPrimLinkable.ConvertLinkset,oldT={1},newT={2}", LocalID, LinksetType, newType);
244
245 // Set the implementation type first so the call to BSLinkset.Factory gets the new type.
246 this.LinksetType = newType;
247
248 BSLinkset oldLinkset = this.Linkset;
249 BSLinkset newLinkset = BSLinkset.Factory(PhysScene, this);
250
251 this.Linkset = newLinkset;
252
253 // Pick up any physical dependencies this linkset might have in the physics engine.
254 oldLinkset.RemoveDependencies(this);
255
256 // Create a list of the children (mainly because can't interate through a list that's changing)
257 List<BSPrimLinkable> children = new List<BSPrimLinkable>();
258 oldLinkset.ForEachMember((child) =>
259 {
260 if (!oldLinkset.IsRoot(child))
261 children.Add(child);
262 return false; // 'false' says to continue to next member
263 });
264
265 // Remove the children from the old linkset and add to the new (will be a new instance from the factory)
266 foreach (BSPrimLinkable child in children)
267 {
268 oldLinkset.RemoveMeFromLinkset(child, true /*inTaintTime*/);
269 }
270 foreach (BSPrimLinkable child in children)
271 {
272 newLinkset.AddMeToLinkset(child);
273 child.Linkset = newLinkset;
274 }
275
276 // Force the shape and linkset to get reconstructed
277 newLinkset.Refresh(this);
278 this.ForceBodyShapeRebuild(true /* inTaintTime */);
279 }
280 return ret;
281 }
282
283 #region Extension
284 public override object Extension(string pFunct, params object[] pParams)
285 {
286 DetailLog("{0} BSPrimLinkable.Extension,op={1},nParam={2}", LocalID, pFunct, pParams.Length);
287 object ret = null;
288 switch (pFunct)
289 {
290 // physGetLinksetType();
291 // pParams = [ BSPhysObject root, null ]
292 case ExtendedPhysics.PhysFunctGetLinksetType:
293 {
294 ret = (object)LinksetType;
295 DetailLog("{0},BSPrimLinkable.Extension.physGetLinksetType,type={1}", LocalID, ret);
296 break;
297 }
298 // physSetLinksetType(type);
299 // pParams = [ BSPhysObject root, null, integer type ]
300 case ExtendedPhysics.PhysFunctSetLinksetType:
301 {
302 if (pParams.Length > 2)
303 {
304 BSLinkset.LinksetImplementation linksetType = (BSLinkset.LinksetImplementation)pParams[2];
305 if (Linkset.IsRoot(this))
306 {
307 PhysScene.TaintedObject(LocalID, "BSPrim.PhysFunctSetLinksetType", delegate()
308 {
309 // Cause the linkset type to change
310 DetailLog("{0},BSPrimLinkable.Extension.physSetLinksetType, oldType={1},newType={2}",
311 LocalID, Linkset.LinksetImpl, linksetType);
312 ConvertLinkset(linksetType);
313 });
314 }
315 ret = (object)(int)linksetType;
316 }
317 break;
318 }
319 // physChangeLinkType(linknum, typeCode);
320 // pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
321 case ExtendedPhysics.PhysFunctChangeLinkType:
322 {
323 ret = Linkset.Extension(pFunct, pParams);
324 break;
325 }
326 // physGetLinkType(linknum);
327 // pParams = [ BSPhysObject root, BSPhysObject child ]
328 case ExtendedPhysics.PhysFunctGetLinkType:
329 {
330 ret = Linkset.Extension(pFunct, pParams);
331 break;
332 }
333 // physChangeLinkParams(linknum, [code, value, code, value, ...]);
334 // pParams = [ BSPhysObject root, BSPhysObject child, object[] [ string op, object opParam, string op, object opParam, ... ] ]
335 case ExtendedPhysics.PhysFunctChangeLinkParams:
336 {
337 ret = Linkset.Extension(pFunct, pParams);
338 break;
339 }
340 default:
341 ret = base.Extension(pFunct, pParams);
342 break;
178 } 343 }
179 return base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth); 344 return ret;
180 } 345 }
346 #endregion // Extension
181} 347}
182} 348}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 9818b05..b3dfa41 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -56,12 +56,23 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
56 public string BulletEngineName { get; private set; } 56 public string BulletEngineName { get; private set; }
57 public BSAPITemplate PE; 57 public BSAPITemplate PE;
58 58
59 // If the physics engine is running on a separate thread
60 public Thread m_physicsThread;
61
59 public Dictionary<uint, BSPhysObject> PhysObjects; 62 public Dictionary<uint, BSPhysObject> PhysObjects;
60 public BSShapeCollection Shapes; 63 public BSShapeCollection Shapes;
61 64
62 // Keeping track of the objects with collisions so we can report begin and end of a collision 65 // Keeping track of the objects with collisions so we can report begin and end of a collision
63 public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>(); 66 public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>();
64 public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>(); 67 public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>();
68
69 // All the collision processing is protected with this lock object
70 public Object CollisionLock = new Object();
71
72 // Properties are updated here
73 public Object UpdateLock = new Object();
74 public HashSet<BSPhysObject> ObjectsWithUpdates = new HashSet<BSPhysObject>();
75
65 // Keep track of all the avatars so we can send them a collision event 76 // Keep track of all the avatars so we can send them a collision event
66 // every tick so OpenSim will update its animation. 77 // every tick so OpenSim will update its animation.
67 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>(); 78 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
@@ -77,12 +88,22 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
77 public BSConstraintCollection Constraints { get; private set; } 88 public BSConstraintCollection Constraints { get; private set; }
78 89
79 // Simulation parameters 90 // Simulation parameters
91 internal float m_physicsStepTime; // if running independently, the interval simulated by default
92
80 internal int m_maxSubSteps; 93 internal int m_maxSubSteps;
81 internal float m_fixedTimeStep; 94 internal float m_fixedTimeStep;
82 internal long m_simulationStep = 0; 95
83 internal float NominalFrameRate { get; set; } 96 internal float m_simulatedTime; // the time simulated previously. Used for physics framerate calc.
97
98 internal long m_simulationStep = 0; // The current simulation step.
84 public long SimulationStep { get { return m_simulationStep; } } 99 public long SimulationStep { get { return m_simulationStep; } }
85 internal float LastTimeStep { get; private set; } 100 // A number to use for SimulationStep that is probably not any step value
101 // Used by the collision code (which remembers the step when a collision happens) to remember not any simulation step.
102 public static long NotASimulationStep = -1234;
103
104 internal float LastTimeStep { get; private set; } // The simulation time from the last invocation of Simulate()
105
106 internal float NominalFrameRate { get; set; } // Parameterized ideal frame rate that simulation is scaled to
86 107
87 // Physical objects can register for prestep or poststep events 108 // Physical objects can register for prestep or poststep events
88 public delegate void PreStepAction(float timeStep); 109 public delegate void PreStepAction(float timeStep);
@@ -90,7 +111,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
90 public event PreStepAction BeforeStep; 111 public event PreStepAction BeforeStep;
91 public event PostStepAction AfterStep; 112 public event PostStepAction AfterStep;
92 113
93 // A value of the time now so all the collision and update routines do not have to get their own 114 // A value of the time 'now' so all the collision and update routines do not have to get their own
94 // Set to 'now' just before all the prims and actors are called for collisions and updates 115 // Set to 'now' just before all the prims and actors are called for collisions and updates
95 public int SimulationNowTime { get; private set; } 116 public int SimulationNowTime { get; private set; }
96 117
@@ -136,12 +157,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
136 public delegate void TaintCallback(); 157 public delegate void TaintCallback();
137 private struct TaintCallbackEntry 158 private struct TaintCallbackEntry
138 { 159 {
160 public String originator;
139 public String ident; 161 public String ident;
140 public TaintCallback callback; 162 public TaintCallback callback;
141 public TaintCallbackEntry(string i, TaintCallback c) 163 public TaintCallbackEntry(string pIdent, TaintCallback pCallBack)
164 {
165 originator = BSScene.DetailLogZero;
166 ident = pIdent;
167 callback = pCallBack;
168 }
169 public TaintCallbackEntry(string pOrigin, string pIdent, TaintCallback pCallBack)
142 { 170 {
143 ident = i; 171 originator = pOrigin;
144 callback = c; 172 ident = pIdent;
173 callback = pCallBack;
145 } 174 }
146 } 175 }
147 private Object _taintLock = new Object(); // lock for using the next object 176 private Object _taintLock = new Object(); // lock for using the next object
@@ -188,6 +217,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
188 PhysObjects = new Dictionary<uint, BSPhysObject>(); 217 PhysObjects = new Dictionary<uint, BSPhysObject>();
189 Shapes = new BSShapeCollection(this); 218 Shapes = new BSShapeCollection(this);
190 219
220 m_simulatedTime = 0f;
221 LastTimeStep = 0.1f;
222
191 // Allocate pinned memory to pass parameters. 223 // Allocate pinned memory to pass parameters.
192 UnmanagedParams = new ConfigurationParameters[1]; 224 UnmanagedParams = new ConfigurationParameters[1];
193 225
@@ -202,8 +234,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
202 // can be left in and every call doesn't have to check for null. 234 // can be left in and every call doesn't have to check for null.
203 if (m_physicsLoggingEnabled) 235 if (m_physicsLoggingEnabled)
204 { 236 {
205 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); 237 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes, m_physicsLoggingDoFlush);
206 PhysicsLogging.ErrorLogger = m_log; // for DEBUG. Let's the logger output error messages. 238 PhysicsLogging.ErrorLogger = m_log; // for DEBUG. Let's the logger output its own error messages.
207 } 239 }
208 else 240 else
209 { 241 {
@@ -227,10 +259,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
227 TerrainManager = new BSTerrainManager(this); 259 TerrainManager = new BSTerrainManager(this);
228 TerrainManager.CreateInitialGroundPlaneAndTerrain(); 260 TerrainManager.CreateInitialGroundPlaneAndTerrain();
229 261
230 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation); 262 // Put some informational messages into the log file.
263 m_log.InfoFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation);
231 264
232 InTaintTime = false; 265 InTaintTime = false;
233 m_initialized = true; 266 m_initialized = true;
267
268 // If the physics engine runs on its own thread, start same.
269 if (BSParam.UseSeparatePhysicsThread)
270 {
271 // The physics simulation should happen independently of the heartbeat loop
272 m_physicsThread = new Thread(BulletSPluginPhysicsThread);
273 m_physicsThread.Name = BulletEngineName;
274 m_physicsThread.Start();
275 }
234 } 276 }
235 277
236 // All default parameter values are set here. There should be no values set in the 278 // All default parameter values are set here. There should be no values set in the
@@ -268,6 +310,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
268 // Do any replacements in the parameters 310 // Do any replacements in the parameters
269 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); 311 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
270 } 312 }
313 else
314 {
315 // Nothing in the configuration INI file so assume unmanaged and other defaults.
316 BulletEngineName = "BulletUnmanaged";
317 m_physicsLoggingEnabled = false;
318 VehicleLoggingEnabled = false;
319 }
271 320
272 // The material characteristics. 321 // The material characteristics.
273 BSMaterials.InitializeFromDefaults(Params); 322 BSMaterials.InitializeFromDefaults(Params);
@@ -311,11 +360,22 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
311 360
312 switch (selectionName) 361 switch (selectionName)
313 { 362 {
363 case "bullet":
314 case "bulletunmanaged": 364 case "bulletunmanaged":
315 ret = new BSAPIUnman(engineName, this); 365 ret = new BSAPIUnman(engineName, this);
316 break; 366 break;
317 case "bulletxna": 367 case "bulletxna":
318 ret = new BSAPIXNA(engineName, this); 368 ret = new BSAPIXNA(engineName, this);
369 // Disable some features that are not implemented in BulletXNA
370 m_log.InfoFormat("{0} Disabling some physics features not implemented by BulletXNA", LogHeader);
371 m_log.InfoFormat("{0} Disabling ShouldUseBulletHACD", LogHeader);
372 BSParam.ShouldUseBulletHACD = false;
373 m_log.InfoFormat("{0} Disabling ShouldUseSingleConvexHullForPrims", LogHeader);
374 BSParam.ShouldUseSingleConvexHullForPrims = false;
375 m_log.InfoFormat("{0} Disabling ShouldUseGImpactShapeForPrims", LogHeader);
376 BSParam.ShouldUseGImpactShapeForPrims = false;
377 m_log.InfoFormat("{0} Setting terrain implimentation to Heightmap", LogHeader);
378 BSParam.TerrainImplementation = (float)BSTerrainPhys.TerrainImplementation.Heightmap;
319 break; 379 break;
320 } 380 }
321 381
@@ -325,7 +385,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
325 } 385 }
326 else 386 else
327 { 387 {
328 m_log.WarnFormat("{0} Selected bullet engine {1} -> {2}/{3}", LogHeader, engineName, ret.BulletEngineName, ret.BulletEngineVersion); 388 m_log.InfoFormat("{0} Selected bullet engine {1} -> {2}/{3}", LogHeader, engineName, ret.BulletEngineName, ret.BulletEngineVersion);
329 } 389 }
330 390
331 return ret; 391 return ret;
@@ -478,25 +538,41 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
478 #endregion // Prim and Avatar addition and removal 538 #endregion // Prim and Avatar addition and removal
479 539
480 #region Simulation 540 #region Simulation
481 // Simulate one timestep 541
542 // Call from the simulator to send physics information to the simulator objects.
543 // This pushes all the collision and property update events into the objects in
544 // the simulator and, since it is on the heartbeat thread, there is an implicit
545 // locking of those data structures from other heartbeat events.
546 // If the physics engine is running on a separate thread, the update information
547 // will be in the ObjectsWithCollions and ObjectsWithUpdates structures.
482 public override float Simulate(float timeStep) 548 public override float Simulate(float timeStep)
483 { 549 {
550 if (!BSParam.UseSeparatePhysicsThread)
551 {
552 DoPhysicsStep(timeStep);
553 }
554 return SendUpdatesToSimulator(timeStep);
555 }
556
557 // Call the physics engine to do one 'timeStep' and collect collisions and updates
558 // into ObjectsWithCollisions and ObjectsWithUpdates data structures.
559 private void DoPhysicsStep(float timeStep)
560 {
484 // prevent simulation until we've been initialized 561 // prevent simulation until we've been initialized
485 if (!m_initialized) return 5.0f; 562 if (!m_initialized) return;
486 563
487 LastTimeStep = timeStep; 564 LastTimeStep = timeStep;
488 565
489 int updatedEntityCount = 0; 566 int updatedEntityCount = 0;
490 int collidersCount = 0; 567 int collidersCount = 0;
491 568
492 int beforeTime = 0; 569 int beforeTime = Util.EnvironmentTickCount();
493 int simTime = 0; 570 int simTime = 0;
494 571
495 // update the prim states while we know the physics engine is not busy
496 int numTaints = _taintOperations.Count; 572 int numTaints = _taintOperations.Count;
497
498 InTaintTime = true; // Only used for debugging so locking is not necessary. 573 InTaintTime = true; // Only used for debugging so locking is not necessary.
499 574
575 // update the prim states while we know the physics engine is not busy
500 ProcessTaints(); 576 ProcessTaints();
501 577
502 // Some of the physical objects requre individual, pre-step calls 578 // Some of the physical objects requre individual, pre-step calls
@@ -519,18 +595,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
519 int numSubSteps = 0; 595 int numSubSteps = 0;
520 try 596 try
521 { 597 {
522 if (PhysicsLogging.Enabled)
523 beforeTime = Util.EnvironmentTickCount();
524
525 numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); 598 numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);
526 599
527 if (PhysicsLogging.Enabled)
528 {
529 simTime = Util.EnvironmentTickCountSubtract(beforeTime);
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 }
534 } 600 }
535 catch (Exception e) 601 catch (Exception e)
536 { 602 {
@@ -542,77 +608,63 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
542 collidersCount = 0; 608 collidersCount = 0;
543 } 609 }
544 610
611 // Make the physics engine dump useful statistics periodically
545 if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0)) 612 if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0))
546 PE.DumpPhysicsStatistics(World); 613 PE.DumpPhysicsStatistics(World);
547 614
548 // Get a value for 'now' so all the collision and update routines don't have to get their own. 615 // Get a value for 'now' so all the collision and update routines don't have to get their own.
549 SimulationNowTime = Util.EnvironmentTickCount(); 616 SimulationNowTime = Util.EnvironmentTickCount();
550 617
551 // If there were collisions, process them by sending the event to the prim. 618 // Send collision information to the colliding objects. The objects decide if the collision
552 // Collisions must be processed before updates. 619 // is 'real' (like linksets don't collide with themselves) and the individual objects
553 if (collidersCount > 0) 620 // know if the simulator has subscribed to collisions.
621 lock (CollisionLock)
554 { 622 {
555 for (int ii = 0; ii < collidersCount; ii++) 623 if (collidersCount > 0)
556 { 624 {
557 uint cA = m_collisionArray[ii].aID; 625 for (int ii = 0; ii < collidersCount; ii++)
558 uint cB = m_collisionArray[ii].bID;
559 Vector3 point = m_collisionArray[ii].point;
560 Vector3 normal = m_collisionArray[ii].normal;
561 float penetration = m_collisionArray[ii].penetration;
562 SendCollision(cA, cB, point, normal, penetration);
563 SendCollision(cB, cA, point, -normal, penetration);
564 }
565 }
566
567 // The above SendCollision's batch up the collisions on the objects.
568 // Now push the collisions into the simulator.
569 if (ObjectsWithCollisions.Count > 0)
570 {
571 foreach (BSPhysObject bsp in ObjectsWithCollisions)
572 if (!bsp.SendCollisions())
573 { 626 {
574 // If the object is done colliding, see that it's removed from the colliding list 627 uint cA = m_collisionArray[ii].aID;
575 ObjectsWithNoMoreCollisions.Add(bsp); 628 uint cB = m_collisionArray[ii].bID;
629 Vector3 point = m_collisionArray[ii].point;
630 Vector3 normal = m_collisionArray[ii].normal;
631 float penetration = m_collisionArray[ii].penetration;
632 SendCollision(cA, cB, point, normal, penetration);
633 SendCollision(cB, cA, point, -normal, penetration);
576 } 634 }
635 }
577 } 636 }
578 637
579 // This is a kludge to get avatar movement updates. 638 // If any of the objects had updated properties, tell the managed objects about the update
580 // The simulator expects collisions for avatars even if there are have been no collisions. 639 // and remember that there was a change so it will be passed to the simulator.
581 // The event updates avatar animations and stuff. 640 lock (UpdateLock)
582 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
583 foreach (BSPhysObject bsp in m_avatars)
584 if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
585 bsp.SendCollisions();
586
587 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
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.
592 if (ObjectsWithNoMoreCollisions.Count > 0)
593 {
594 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
595 ObjectsWithCollisions.Remove(po);
596 ObjectsWithNoMoreCollisions.Clear();
597 }
598 // Done with collisions.
599
600 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
601 if (updatedEntityCount > 0)
602 { 641 {
603 for (int ii = 0; ii < updatedEntityCount; ii++) 642 if (updatedEntityCount > 0)
604 { 643 {
605 EntityProperties entprop = m_updateArray[ii]; 644 for (int ii = 0; ii < updatedEntityCount; ii++)
606 BSPhysObject pobj;
607 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
608 { 645 {
609 pobj.UpdateProperties(entprop); 646 EntityProperties entprop = m_updateArray[ii];
647 BSPhysObject pobj;
648 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
649 {
650 if (pobj.IsInitialized)
651 pobj.UpdateProperties(entprop);
652 }
610 } 653 }
611 } 654 }
612 } 655 }
613 656
657 // Some actors want to know when the simulation step is complete.
614 TriggerPostStepEvent(timeStep); 658 TriggerPostStepEvent(timeStep);
615 659
660 simTime = Util.EnvironmentTickCountSubtract(beforeTime);
661 if (PhysicsLogging.Enabled)
662 {
663 DetailLog("{0},DoPhysicsStep,complete,frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
664 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
665 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
666 }
667
616 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. 668 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
617 // Only enable this in a limited test world with few objects. 669 // Only enable this in a limited test world with few objects.
618 if (m_physicsPhysicalDumpEnabled) 670 if (m_physicsPhysicalDumpEnabled)
@@ -621,7 +673,84 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
621 // The physics engine returns the number of milliseconds it simulated this call. 673 // The physics engine returns the number of milliseconds it simulated this call.
622 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 674 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
623 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55). 675 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55).
624 return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; 676 m_simulatedTime += (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
677 }
678
679 // Called by a BSPhysObject to note that it has changed properties and this information
680 // should be passed up to the simulator at the proper time.
681 // Note: this is called by the BSPhysObject from invocation via DoPhysicsStep() above so
682 // this is is under UpdateLock.
683 public void PostUpdate(BSPhysObject updatee)
684 {
685 ObjectsWithUpdates.Add(updatee);
686 }
687
688 // The simulator thinks it is physics time so return all the collisions and position
689 // updates that were collected in actual physics simulation.
690 private float SendUpdatesToSimulator(float timeStep)
691 {
692 if (!m_initialized) return 5.0f;
693
694 DetailLog("{0},SendUpdatesToSimulator,collisions={1},updates={2},simedTime={3}",
695 BSScene.DetailLogZero, ObjectsWithCollisions.Count, ObjectsWithUpdates.Count, m_simulatedTime);
696 // Push the collisions into the simulator.
697 lock (CollisionLock)
698 {
699 if (ObjectsWithCollisions.Count > 0)
700 {
701 foreach (BSPhysObject bsp in ObjectsWithCollisions)
702 if (!bsp.SendCollisions())
703 {
704 // If the object is done colliding, see that it's removed from the colliding list
705 ObjectsWithNoMoreCollisions.Add(bsp);
706 }
707 }
708
709 // This is a kludge to get avatar movement updates.
710 // The simulator expects collisions for avatars even if there are have been no collisions.
711 // The event updates avatar animations and stuff.
712 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
713 foreach (BSPhysObject bsp in m_avatars)
714 if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
715 bsp.SendCollisions();
716
717 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
718 // Not done above because it is inside an iteration of ObjectWithCollisions.
719 // This complex collision processing is required to create an empty collision
720 // event call after all real collisions have happened on an object. This allows
721 // the simulator to generate the 'collision end' event.
722 if (ObjectsWithNoMoreCollisions.Count > 0)
723 {
724 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
725 ObjectsWithCollisions.Remove(po);
726 ObjectsWithNoMoreCollisions.Clear();
727 }
728 }
729
730 // Call the simulator for each object that has physics property updates.
731 HashSet<BSPhysObject> updatedObjects = null;
732 lock (UpdateLock)
733 {
734 if (ObjectsWithUpdates.Count > 0)
735 {
736 updatedObjects = ObjectsWithUpdates;
737 ObjectsWithUpdates = new HashSet<BSPhysObject>();
738 }
739 }
740 if (updatedObjects != null)
741 {
742 foreach (BSPhysObject obj in updatedObjects)
743 {
744 obj.RequestPhysicsterseUpdate();
745 }
746 updatedObjects.Clear();
747 }
748
749 // Return the framerate simulated to give the above returned results.
750 // (Race condition here but this is just bookkeeping so rare mistakes do not merit a lock).
751 float simTime = m_simulatedTime;
752 m_simulatedTime = 0f;
753 return simTime;
625 } 754 }
626 755
627 // Something has collided 756 // Something has collided
@@ -640,21 +769,49 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
640 return; 769 return;
641 } 770 }
642 771
643 // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called. 772 // Note: the terrain is not in the physical object list so 'collidee' can be null when Collide() is called.
644 BSPhysObject collidee = null; 773 BSPhysObject collidee = null;
645 PhysObjects.TryGetValue(collidingWith, out collidee); 774 PhysObjects.TryGetValue(collidingWith, out collidee);
646 775
647 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); 776 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
648 777
649 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) 778 if (collider.IsInitialized)
650 { 779 {
651 // If a collision was posted, remember to send it to the simulator 780 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
652 ObjectsWithCollisions.Add(collider); 781 {
782 // If a collision was 'good', remember to send it to the simulator
783 ObjectsWithCollisions.Add(collider);
784 }
653 } 785 }
654 786
655 return; 787 return;
656 } 788 }
657 789
790 public void BulletSPluginPhysicsThread()
791 {
792 while (m_initialized)
793 {
794 int beginSimulationRealtimeMS = Util.EnvironmentTickCount();
795 DoPhysicsStep(BSParam.PhysicsTimeStep);
796 int simulationRealtimeMS = Util.EnvironmentTickCountSubtract(beginSimulationRealtimeMS);
797 int simulationTimeVsRealtimeDifferenceMS = ((int)(BSParam.PhysicsTimeStep*1000f)) - simulationRealtimeMS;
798
799 if (simulationTimeVsRealtimeDifferenceMS > 0)
800 {
801 // The simulation of the time interval took less than realtime.
802 // Do a sleep for the rest of realtime.
803 Thread.Sleep(simulationTimeVsRealtimeDifferenceMS);
804 }
805 else
806 {
807 // The simulation took longer than realtime.
808 // Do some scaling of simulation time.
809 // TODO.
810 DetailLog("{0},BulletSPluginPhysicsThread,longerThanRealtime={1}", BSScene.DetailLogZero, simulationTimeVsRealtimeDifferenceMS);
811 }
812 }
813 }
814
658 #endregion // Simulation 815 #endregion // Simulation
659 816
660 public override void GetResults() { } 817 public override void GetResults() { }
@@ -717,6 +874,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
717 874
718 public override bool IsThreaded { get { return false; } } 875 public override bool IsThreaded { get { return false; } }
719 876
877 #region Extensions
878 public override object Extension(string pFunct, params object[] pParams)
879 {
880 DetailLog("{0} BSScene.Extension,op={1}", DetailLogZero, pFunct);
881 return base.Extension(pFunct, pParams);
882 }
883 #endregion // Extensions
884
720 #region Taints 885 #region Taints
721 // The simulation execution order is: 886 // The simulation execution order is:
722 // Simulate() 887 // Simulate()
@@ -731,26 +896,37 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
731 // Calls to the PhysicsActors can't directly call into the physics engine 896 // Calls to the PhysicsActors can't directly call into the physics engine
732 // because it might be busy. We delay changes to a known time. 897 // because it might be busy. We delay changes to a known time.
733 // We rely on C#'s closure to save and restore the context for the delegate. 898 // We rely on C#'s closure to save and restore the context for the delegate.
734 public void TaintedObject(String ident, TaintCallback callback) 899 public void TaintedObject(string pOriginator, string pIdent, TaintCallback pCallback)
735 { 900 {
736 if (!m_initialized) return; 901 TaintedObject(false /*inTaintTime*/, pOriginator, pIdent, pCallback);
737 902 }
738 lock (_taintLock) 903 public void TaintedObject(uint pOriginator, String pIdent, TaintCallback pCallback)
739 { 904 {
740 _taintOperations.Add(new TaintCallbackEntry(ident, callback)); 905 TaintedObject(false /*inTaintTime*/, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback);
741 } 906 }
742 907 public void TaintedObject(bool inTaintTime, String pIdent, TaintCallback pCallback)
743 return; 908 {
909 TaintedObject(inTaintTime, BSScene.DetailLogZero, pIdent, pCallback);
910 }
911 public void TaintedObject(bool inTaintTime, uint pOriginator, String pIdent, TaintCallback pCallback)
912 {
913 TaintedObject(inTaintTime, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback);
744 } 914 }
745
746 // Sometimes a potentially tainted operation can be used in and out of taint time. 915 // Sometimes a potentially tainted operation can be used in and out of taint time.
747 // This routine executes the command immediately if in taint-time otherwise it is queued. 916 // This routine executes the command immediately if in taint-time otherwise it is queued.
748 public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) 917 public void TaintedObject(bool inTaintTime, string pOriginator, string pIdent, TaintCallback pCallback)
749 { 918 {
919 if (!m_initialized) return;
920
750 if (inTaintTime) 921 if (inTaintTime)
751 callback(); 922 pCallback();
752 else 923 else
753 TaintedObject(ident, callback); 924 {
925 lock (_taintLock)
926 {
927 _taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback));
928 }
929 }
754 } 930 }
755 931
756 private void TriggerPreStepEvent(float timeStep) 932 private void TriggerPreStepEvent(float timeStep)
@@ -780,7 +956,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
780 956
781 private void ProcessRegularTaints() 957 private void ProcessRegularTaints()
782 { 958 {
783 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process 959 if (m_initialized && _taintOperations.Count > 0) // save allocating new list if there is nothing to process
784 { 960 {
785 // swizzle a new list into the list location so we can process what's there 961 // swizzle a new list into the list location so we can process what's there
786 List<TaintCallbackEntry> oldList; 962 List<TaintCallbackEntry> oldList;
@@ -794,7 +970,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
794 { 970 {
795 try 971 try
796 { 972 {
797 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG 973 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", tcbe.originator, tcbe.ident); // DEBUG DEBUG DEBUG
798 tcbe.callback(); 974 tcbe.callback();
799 } 975 }
800 catch (Exception e) 976 catch (Exception e)
@@ -811,10 +987,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
811 // will replace any previous operation by the same object. 987 // will replace any previous operation by the same object.
812 public void PostTaintObject(String ident, uint ID, TaintCallback callback) 988 public void PostTaintObject(String ident, uint ID, TaintCallback callback)
813 { 989 {
814 string uniqueIdent = ident + "-" + ID.ToString(); 990 string IDAsString = ID.ToString();
991 string uniqueIdent = ident + "-" + IDAsString;
815 lock (_taintLock) 992 lock (_taintLock)
816 { 993 {
817 _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); 994 _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(IDAsString, uniqueIdent, callback);
818 } 995 }
819 996
820 return; 997 return;
@@ -823,7 +1000,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
823 // Taints that happen after the normal taint processing but before the simulation step. 1000 // Taints that happen after the normal taint processing but before the simulation step.
824 private void ProcessPostTaintTaints() 1001 private void ProcessPostTaintTaints()
825 { 1002 {
826 if (_postTaintOperations.Count > 0) 1003 if (m_initialized && _postTaintOperations.Count > 0)
827 { 1004 {
828 Dictionary<string, TaintCallbackEntry> oldList; 1005 Dictionary<string, TaintCallbackEntry> oldList;
829 lock (_taintLock) 1006 lock (_taintLock)
@@ -924,7 +1101,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
924 string xval = val; 1101 string xval = val;
925 List<uint> xlIDs = lIDs; 1102 List<uint> xlIDs = lIDs;
926 string xparm = parm; 1103 string xparm = parm;
927 TaintedObject("BSScene.UpdateParameterSet", delegate() { 1104 TaintedObject(DetailLogZero, "BSScene.UpdateParameterSet", delegate() {
928 BSParam.ParameterDefnBase thisParam; 1105 BSParam.ParameterDefnBase thisParam;
929 if (BSParam.TryGetParameter(xparm, out thisParam)) 1106 if (BSParam.TryGetParameter(xparm, out thisParam))
930 { 1107 {
@@ -963,8 +1140,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
963 public void DetailLog(string msg, params Object[] args) 1140 public void DetailLog(string msg, params Object[] args)
964 { 1141 {
965 PhysicsLogging.Write(msg, args); 1142 PhysicsLogging.Write(msg, args);
966 // Add the Flush() if debugging crashes. Gets all the messages written out.
967 if (m_physicsLoggingDoFlush) PhysicsLogging.Flush();
968 } 1143 }
969 // Used to fill in the LocalID when there isn't one. It's the correct number of characters. 1144 // Used to fill in the LocalID when there isn't one. It's the correct number of characters.
970 public const string DetailLogZero = "0000000000"; 1145 public const string DetailLogZero = "0000000000";
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 220fbbc..32bbc8f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -38,38 +38,15 @@ public sealed class BSShapeCollection : IDisposable
38{ 38{
39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; 39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
40 40
41 private BSScene PhysicsScene { get; set; } 41 private BSScene m_physicsScene { get; set; }
42 42
43 private Object m_collectionActivityLock = new Object(); 43 private Object m_collectionActivityLock = new Object();
44 44
45 // Description of a Mesh
46 private struct MeshDesc
47 {
48 public BulletShape shape;
49 public int referenceCount;
50 public DateTime lastReferenced;
51 public UInt64 shapeKey;
52 }
53
54 // Description of a hull.
55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
56 private struct HullDesc
57 {
58 public BulletShape shape;
59 public int referenceCount;
60 public DateTime lastReferenced;
61 public UInt64 shapeKey;
62 }
63
64 // The sharable set of meshes and hulls. Indexed by their shape hash.
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67
68 private bool DDetail = false; 45 private bool DDetail = false;
69 46
70 public BSShapeCollection(BSScene physScene) 47 public BSShapeCollection(BSScene physScene)
71 { 48 {
72 PhysicsScene = physScene; 49 m_physicsScene = physScene;
73 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?) 50 // 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 51 // 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 52 // DetailLog statements. When debugging slows down, this and the protected logging
@@ -86,22 +63,18 @@ public sealed class BSShapeCollection : IDisposable
86 // Mostly used for changing bodies out from under Linksets. 63 // Mostly used for changing bodies out from under Linksets.
87 // Useful for other cases where parameters need saving. 64 // Useful for other cases where parameters need saving.
88 // Passing 'null' says no callback. 65 // Passing 'null' says no callback.
89 public delegate void ShapeDestructionCallback(BulletShape shape); 66 public delegate void PhysicalDestructionCallback(BulletBody pBody, BulletShape pShape);
90 public delegate void BodyDestructionCallback(BulletBody body);
91 67
92 // Called to update/change the body and shape for an object. 68 // Called to update/change the body and shape for an object.
93 // First checks the shape and updates that if necessary then makes 69 // The object has some shape and body on it. Here we decide if that is the correct shape
94 // sure the body is of the right type. 70 // for the current state of the object (static/dynamic/...).
71 // If bodyCallback is not null, it is called if either the body or the shape are changed
72 // so dependencies (like constraints) can be removed before the physical object is dereferenced.
95 // Return 'true' if either the body or the shape changed. 73 // Return 'true' if either the body or the shape changed.
96 // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before 74 // Called at taint-time.
97 // the current shape or body is destroyed. This allows the caller to remove any 75 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback)
98 // higher level dependencies on the shape or body. Mostly used for LinkSets to
99 // remove the physical constraints before the body is destroyed.
100 // Called at taint-time!!
101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim,
102 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
103 { 76 {
104 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); 77 m_physicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
105 78
106 bool ret = false; 79 bool ret = false;
107 80
@@ -111,12 +84,12 @@ public sealed class BSShapeCollection : IDisposable
111 // Do we have the correct geometry for this type of object? 84 // Do we have the correct geometry for this type of object?
112 // Updates prim.BSShape with information/pointers to shape. 85 // Updates prim.BSShape with information/pointers to shape.
113 // Returns 'true' of BSShape is changed to a new shape. 86 // Returns 'true' of BSShape is changed to a new shape.
114 bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); 87 bool newGeom = CreateGeom(forceRebuild, prim, bodyCallback);
115 // If we had to select a new shape geometry for the object, 88 // If we had to select a new shape geometry for the object,
116 // rebuild the body around it. 89 // rebuild the body around it.
117 // Updates prim.BSBody with information/pointers to requested body 90 // Updates prim.BSBody with information/pointers to requested body
118 // Returns 'true' if BSBody was changed. 91 // Returns 'true' if BSBody was changed.
119 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, bodyCallback); 92 bool newBody = CreateBody((newGeom || forceRebuild), prim, m_physicsScene.World, bodyCallback);
120 ret = newGeom || newBody; 93 ret = newGeom || newBody;
121 } 94 }
122 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", 95 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
@@ -127,274 +100,20 @@ public sealed class BSShapeCollection : IDisposable
127 100
128 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim) 101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
129 { 102 {
130 return GetBodyAndShape(forceRebuild, sim, prim, null, null); 103 return GetBodyAndShape(forceRebuild, sim, prim, null);
131 }
132
133 // Track another user of a body.
134 // We presume the caller has allocated the body.
135 // Bodies only have one user so the body is just put into the world if not already there.
136 private void ReferenceBody(BulletBody body)
137 {
138 lock (m_collectionActivityLock)
139 {
140 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
141 if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
142 {
143 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body);
144 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
145 }
146 }
147 }
148
149 // Release the usage of a body.
150 // Called when releasing use of a BSBody. BSShape is handled separately.
151 // Called in taint time.
152 public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback )
153 {
154 if (!body.HasPhysicalBody)
155 return;
156
157 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
158
159 lock (m_collectionActivityLock)
160 {
161 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
162 // If the caller needs to know the old body is going away, pass the event up.
163 if (bodyCallback != null) bodyCallback(body);
164
165 if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
166 {
167 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
168 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
169 }
170
171 // Zero any reference to the shape so it is not freed when the body is deleted.
172 PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
173 PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
174 }
175 }
176
177 // Track the datastructures and use count for a shape.
178 // When creating a hull, this is called first to reference the mesh
179 // and then again to reference the hull.
180 // Meshes and hulls for the same shape have the same hash key.
181 // NOTE that native shapes are not added to the mesh list or removed.
182 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
183 public bool ReferenceShape(BulletShape shape)
184 {
185 bool ret = false;
186 switch (shape.type)
187 {
188 case BSPhysicsShapeType.SHAPE_MESH:
189 MeshDesc meshDesc;
190 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
191 {
192 // There is an existing instance of this mesh.
193 meshDesc.referenceCount++;
194 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
195 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
196 }
197 else
198 {
199 // This is a new reference to a mesh
200 meshDesc.shape = shape.Clone();
201 meshDesc.shapeKey = shape.shapeKey;
202 // We keep a reference to the underlying IMesh data so a hull can be built
203 meshDesc.referenceCount = 1;
204 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
205 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
206 ret = true;
207 }
208 meshDesc.lastReferenced = System.DateTime.Now;
209 Meshes[shape.shapeKey] = meshDesc;
210 break;
211 case BSPhysicsShapeType.SHAPE_HULL:
212 HullDesc hullDesc;
213 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
214 {
215 // There is an existing instance of this hull.
216 hullDesc.referenceCount++;
217 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
218 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
219 }
220 else
221 {
222 // This is a new reference to a hull
223 hullDesc.shape = shape.Clone();
224 hullDesc.shapeKey = shape.shapeKey;
225 hullDesc.referenceCount = 1;
226 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
227 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
228 ret = true;
229
230 }
231 hullDesc.lastReferenced = System.DateTime.Now;
232 Hulls[shape.shapeKey] = hullDesc;
233 break;
234 case BSPhysicsShapeType.SHAPE_UNKNOWN:
235 break;
236 default:
237 // Native shapes are not tracked and they don't go into any list
238 break;
239 }
240 return ret;
241 } 104 }
242 105
243 // Release the usage of a shape. 106 // If the existing prim's shape is to be replaced, remove the tie to the existing shape
244 public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback) 107 // before replacing it.
108 private void DereferenceExistingShape(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
245 { 109 {
246 if (!shape.HasPhysicalShape) 110 if (prim.PhysShape.HasPhysicalShape)
247 return;
248
249 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape");
250
251 if (shape.HasPhysicalShape)
252 {
253 if (shape.isNativeShape)
254 {
255 // Native shapes are not tracked and are released immediately
256 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}",
257 BSScene.DetailLogZero, shape.AddrString);
258 if (shapeCallback != null) shapeCallback(shape);
259 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
260 }
261 else
262 {
263 switch (shape.type)
264 {
265 case BSPhysicsShapeType.SHAPE_HULL:
266 DereferenceHull(shape, shapeCallback);
267 break;
268 case BSPhysicsShapeType.SHAPE_MESH:
269 DereferenceMesh(shape, shapeCallback);
270 break;
271 case BSPhysicsShapeType.SHAPE_COMPOUND:
272 DereferenceCompound(shape, shapeCallback);
273 break;
274 case BSPhysicsShapeType.SHAPE_UNKNOWN:
275 break;
276 default:
277 break;
278 }
279 }
280 }
281 }
282
283 // Count down the reference count for a mesh shape
284 // Called at taint-time.
285 private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback)
286 {
287 MeshDesc meshDesc;
288 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
289 { 111 {
290 meshDesc.referenceCount--; 112 if (shapeCallback != null)
291 // TODO: release the Bullet storage 113 shapeCallback(prim.PhysBody, prim.PhysShape.physShapeInfo);
292 if (shapeCallback != null) shapeCallback(shape); 114 prim.PhysShape.Dereference(m_physicsScene);
293 meshDesc.lastReferenced = System.DateTime.Now;
294 Meshes[shape.shapeKey] = meshDesc;
295 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
296 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
297
298 }
299 }
300
301 // Count down the reference count for a hull shape
302 // Called at taint-time.
303 private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
304 {
305 HullDesc hullDesc;
306 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
307 {
308 hullDesc.referenceCount--;
309 // TODO: release the Bullet storage (aging old entries?)
310
311 // Tell upper layers that, if they have dependencies on this shape, this link is going away
312 if (shapeCallback != null) shapeCallback(shape);
313
314 hullDesc.lastReferenced = System.DateTime.Now;
315 Hulls[shape.shapeKey] = hullDesc;
316 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
317 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
318 }
319 }
320
321 // Remove a reference to a compound shape.
322 // Taking a compound shape apart is a little tricky because if you just delete the
323 // physical shape, it will free all the underlying children. We can't do that because
324 // they could be shared. So, this removes each of the children from the compound and
325 // dereferences them separately before destroying the compound collision object itself.
326 // Called at taint-time.
327 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
328 {
329 if (!PhysicsScene.PE.IsCompound(shape))
330 {
331 // Failed the sanity check!!
332 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
333 LogHeader, shape.type, shape.AddrString);
334 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
335 BSScene.DetailLogZero, shape.type, shape.AddrString);
336 return;
337 }
338
339 int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape);
340 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
341
342 for (int ii = numChildren - 1; ii >= 0; ii--)
343 {
344 BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii);
345 DereferenceAnonCollisionShape(childShape);
346 }
347 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
348 }
349
350 // Sometimes we have a pointer to a collision shape but don't know what type it is.
351 // Figure out type and call the correct dereference routine.
352 // Called at taint-time.
353 private void DereferenceAnonCollisionShape(BulletShape shapeInfo)
354 {
355 MeshDesc meshDesc;
356 HullDesc hullDesc;
357
358 if (TryGetMeshByPtr(shapeInfo, out meshDesc))
359 {
360 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
361 shapeInfo.shapeKey = meshDesc.shapeKey;
362 }
363 else
364 {
365 if (TryGetHullByPtr(shapeInfo, out hullDesc))
366 {
367 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
368 shapeInfo.shapeKey = hullDesc.shapeKey;
369 }
370 else
371 {
372 if (PhysicsScene.PE.IsCompound(shapeInfo))
373 {
374 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
375 }
376 else
377 {
378 if (PhysicsScene.PE.IsNativeShape(shapeInfo))
379 {
380 shapeInfo.isNativeShape = true;
381 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
382 }
383 }
384 }
385 }
386
387 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
388
389 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
390 {
391 DereferenceShape(shapeInfo, null);
392 }
393 else
394 {
395 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}",
396 LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString);
397 } 115 }
116 prim.PhysShape = new BSShapeNull();
398 } 117 }
399 118
400 // Create the geometry information in Bullet for later use. 119 // Create the geometry information in Bullet for later use.
@@ -405,60 +124,41 @@ public sealed class BSShapeCollection : IDisposable
405 // Info in prim.BSShape is updated to the new shape. 124 // Info in prim.BSShape is updated to the new shape.
406 // Returns 'true' if the geometry was rebuilt. 125 // Returns 'true' if the geometry was rebuilt.
407 // Called at taint-time! 126 // Called at taint-time!
408 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) 127 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
409 { 128 {
410 bool ret = false; 129 bool ret = false;
411 bool haveShape = false; 130 bool haveShape = false;
131 bool nativeShapePossible = true;
132 PrimitiveBaseShape pbs = prim.BaseShape;
412 133
413 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) 134 // Kludge to create the capsule for the avatar.
135 // TDOD: Remove/redo this when BSShapeAvatar is working!!
136 BSCharacter theChar = prim as BSCharacter;
137 if (theChar != null)
414 { 138 {
415 // an avatar capsule is close to a native shape (it is not shared) 139 DereferenceExistingShape(prim, shapeCallback);
416 GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback); 140 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
417 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); 141 BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE);
418 ret = true; 142 ret = true;
419 haveShape = true; 143 haveShape = true;
420 } 144 }
421 145
422 // Compound shapes are handled special as they are rebuilt from scratch.
423 // This isn't too great a hardship since most of the child shapes will have already been created.
424 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
425 {
426 ret = GetReferenceToCompoundShape(prim, shapeCallback);
427 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
428 haveShape = true;
429 }
430
431 if (!haveShape)
432 {
433 ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback);
434 }
435
436 return ret;
437 }
438
439 // Create a mesh, hull or native shape.
440 // Return 'true' if the prim's shape was changed.
441 public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
442 {
443 bool ret = false;
444 bool haveShape = false;
445 bool nativeShapePossible = true;
446 PrimitiveBaseShape pbs = prim.BaseShape;
447
448 // If the prim attributes are simple, this could be a simple Bullet native shape 146 // If the prim attributes are simple, this could be a simple Bullet native shape
147 // Native shapes work whether to object is static or physical.
449 if (!haveShape 148 if (!haveShape
450 && nativeShapePossible 149 && nativeShapePossible
451 && pbs != null 150 && pbs != null
452 && !pbs.SculptEntry 151 && PrimHasNoCuts(pbs)
453 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) ) 152 && ( !pbs.SculptEntry || (pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) )
153 )
454 { 154 {
455 // Get the scale of any existing shape so we can see if the new shape is same native type and same size. 155 // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
456 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; 156 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
457 if (prim.PhysShape.HasPhysicalShape) 157 if (prim.PhysShape.HasPhysicalShape)
458 scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape); 158 scaleOfExistingShape = m_physicsScene.PE.GetLocalScaling(prim.PhysShape.physShapeInfo);
459 159
460 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", 160 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
461 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); 161 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.physShapeInfo.shapeType);
462 162
463 // It doesn't look like Bullet scales native spheres so make sure the scales are all equal 163 // It doesn't look like Bullet scales native spheres so make sure the scales are all equal
464 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) 164 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -466,26 +166,30 @@ public sealed class BSShapeCollection : IDisposable
466 { 166 {
467 haveShape = true; 167 haveShape = true;
468 if (forceRebuild 168 if (forceRebuild
469 || prim.Scale != scaleOfExistingShape 169 || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_SPHERE
470 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE 170 )
471 )
472 { 171 {
473 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, 172 DereferenceExistingShape(prim, shapeCallback);
474 FixedShapeKey.KEY_SPHERE, shapeCallback); 173 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
174 BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_SPHERE);
175 ret = true;
475 } 176 }
476 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}", 177 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}",
477 prim.LocalID, forceRebuild, ret, prim.PhysShape); 178 prim.LocalID, forceRebuild, ret, prim.PhysShape);
478 } 179 }
180 // If we didn't make a sphere, maybe a box will work.
479 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 181 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
480 { 182 {
481 haveShape = true; 183 haveShape = true;
482 if (forceRebuild 184 if (forceRebuild
483 || prim.Scale != scaleOfExistingShape 185 || prim.Scale != scaleOfExistingShape
484 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX 186 || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_BOX
485 ) 187 )
486 { 188 {
487 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, 189 DereferenceExistingShape(prim, shapeCallback);
488 FixedShapeKey.KEY_BOX, shapeCallback); 190 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
191 BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
192 ret = true;
489 } 193 }
490 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}", 194 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}",
491 prim.LocalID, forceRebuild, ret, prim.PhysShape); 195 prim.LocalID, forceRebuild, ret, prim.PhysShape);
@@ -502,7 +206,7 @@ public sealed class BSShapeCollection : IDisposable
502 } 206 }
503 207
504 // return 'true' if this shape description does not include any cutting or twisting. 208 // return 'true' if this shape description does not include any cutting or twisting.
505 private bool PrimHasNoCuts(PrimitiveBaseShape pbs) 209 public static bool PrimHasNoCuts(PrimitiveBaseShape pbs)
506 { 210 {
507 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 211 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
508 && pbs.ProfileHollow == 0 212 && pbs.ProfileHollow == 0
@@ -514,7 +218,7 @@ public sealed class BSShapeCollection : IDisposable
514 } 218 }
515 219
516 // return 'true' if the prim's shape was changed. 220 // return 'true' if the prim's shape was changed.
517 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 221 private bool CreateGeomMeshOrHull(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
518 { 222 {
519 223
520 bool ret = false; 224 bool ret = false;
@@ -522,503 +226,121 @@ public sealed class BSShapeCollection : IDisposable
522 // made. Native shapes work in either case. 226 // made. Native shapes work in either case.
523 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) 227 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
524 { 228 {
525 // Update prim.BSShape to reference a hull of this shape. 229 // Use a simple, single mesh convex hull shape if the object is simple enough
526 ret = GetReferenceToHull(prim, shapeCallback); 230 BSShape potentialHull = null;
527 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
528 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
529 }
530 else
531 {
532 ret = GetReferenceToMesh(prim, shapeCallback);
533 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
534 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
535 }
536 return ret;
537 }
538
539 // Creates a native shape and assignes it to prim.BSShape.
540 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
541 private bool GetReferenceToNativeShape(BSPhysObject prim,
542 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey,
543 ShapeDestructionCallback shapeCallback)
544 {
545 // release any previous shape
546 DereferenceShape(prim.PhysShape, shapeCallback);
547
548 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
549
550 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
551 if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
552 prim.LocalID, newShape, prim.Scale);
553
554 // native shapes are scaled by Bullet
555 prim.PhysShape = newShape;
556 return true;
557 }
558
559 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType,
560 FixedShapeKey shapeKey)
561 {
562 BulletShape newShape;
563 // Need to make sure the passed shape information is for the native type.
564 ShapeData nativeShapeData = new ShapeData();
565 nativeShapeData.Type = shapeType;
566 nativeShapeData.ID = prim.LocalID;
567 nativeShapeData.Scale = prim.Scale;
568 nativeShapeData.Size = prim.Scale; // unneeded, I think.
569 nativeShapeData.MeshKey = (ulong)shapeKey;
570 nativeShapeData.HullKey = (ulong)shapeKey;
571
572 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
573 {
574 231
575 newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale); 232 PrimitiveBaseShape pbs = prim.BaseShape;
576 if (DDetail) DetailLog("{0},BSShapeCollection.BuildPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 233 // Use a simple, one section convex shape for prims that are probably convex (no cuts or twists)
577 } 234 if (BSParam.ShouldUseSingleConvexHullForPrims
578 else 235 && pbs != null
579 { 236 && !pbs.SculptEntry
580 // Native shapes are scaled in Bullet so set the scaling to the size 237 && PrimHasNoCuts(pbs)
581 newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData); 238 )
582 239 {
583 } 240 potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim);
584 if (!newShape.HasPhysicalShape) 241 }
585 { 242 // Use the GImpact shape if it is a prim that has some concaveness
586 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 243 if (potentialHull == null
587 LogHeader, prim.LocalID, shapeType); 244 && BSParam.ShouldUseGImpactShapeForPrims
588 } 245 && pbs != null
589 newShape.shapeKey = (System.UInt64)shapeKey; 246 && !pbs.SculptEntry
590 newShape.isNativeShape = true; 247 )
591 248 {
592 return newShape; 249 potentialHull = BSShapeGImpact.GetReference(m_physicsScene, false /* forceRebuild */, prim);
593 } 250 }
594 251 // If not any of the simple cases, just make a hull
595 // Builds a mesh shape in the physical world and updates prim.BSShape. 252 if (potentialHull == null)
596 // Dereferences previous shape in BSShape and adds a reference for this new shape. 253 {
597 // Returns 'true' of a mesh was actually built. Otherwise . 254 potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
598 // Called at taint-time! 255 }
599 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
600 {
601 BulletShape newShape = new BulletShape();
602
603 float lod;
604 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
605
606 // if this new shape is the same as last time, don't recreate the mesh
607 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
608 return false;
609
610 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2},size={3},lod={4}",
611 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
612
613 // Since we're recreating new, get rid of the reference to the previous shape
614 DereferenceShape(prim.PhysShape, shapeCallback);
615
616 newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod);
617 // Take evasive action if the mesh was not constructed.
618 newShape = VerifyMeshCreated(newShape, prim);
619
620 ReferenceShape(newShape);
621
622 prim.PhysShape = newShape;
623
624 return true; // 'true' means a new shape has been added to this prim
625 }
626
627 private BulletShape CreatePhysicalMesh(BSPhysObject prim, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
628 {
629 BulletShape newShape = new BulletShape();
630 256
631 MeshDesc meshDesc; 257 // If the current shape is not what is on the prim at the moment, time to change.
632 if (Meshes.TryGetValue(newMeshKey, out meshDesc)) 258 if (!prim.PhysShape.HasPhysicalShape
633 { 259 || potentialHull.ShapeType != prim.PhysShape.ShapeType
634 // If the mesh has already been built just use it. 260 || potentialHull.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
635 newShape = meshDesc.shape.Clone(); 261 {
262 DereferenceExistingShape(prim, shapeCallback);
263 prim.PhysShape = potentialHull;
264 ret = true;
265 }
266 else
267 {
268 // The current shape on the prim is the correct one. We don't need the potential reference.
269 potentialHull.Dereference(m_physicsScene);
270 }
271 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1}", prim.LocalID, prim.PhysShape);
636 } 272 }
637 else 273 else
638 { 274 {
639 IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, 275 // Non-physical objects should be just meshes.
640 true, 276 BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
641 false, // say it is not physical so a bounding box is not built 277 // If the current shape is not what is on the prim at the moment, time to change.
642 false, // do not cache the mesh and do not use previously built versions 278 if (!prim.PhysShape.HasPhysicalShape
643 false // It's NOT for ODE 279 || potentialMesh.ShapeType != prim.PhysShape.ShapeType
644 ); 280 || potentialMesh.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
645
646 if (meshData != null)
647 { 281 {
648 282 DereferenceExistingShape(prim, shapeCallback);
649 int[] indices = meshData.getIndexListAsInt(); 283 prim.PhysShape = potentialMesh;
650 int realIndicesIndex = indices.Length; 284 ret = true;
651 float[] verticesAsFloats = meshData.getVertexListAsFloat();
652
653 if (BSParam.ShouldRemoveZeroWidthTriangles)
654 {
655 // Remove degenerate triangles. These are triangles with two of the vertices
656 // are the same. This is complicated by the problem that vertices are not
657 // made unique in sculpties so we have to compare the values in the vertex.
658 realIndicesIndex = 0;
659 for (int tri = 0; tri < indices.Length; tri += 3)
660 {
661 // Compute displacements into vertex array for each vertex of the triangle
662 int v1 = indices[tri + 0] * 3;
663 int v2 = indices[tri + 1] * 3;
664 int v3 = indices[tri + 2] * 3;
665 // Check to see if any two of the vertices are the same
666 if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
667 && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
668 && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
669 || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
670 && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
671 && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
672 || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
673 && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
674 && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
675 )
676 {
677 // None of the vertices of the triangles are the same. This is a good triangle;
678 indices[realIndicesIndex + 0] = indices[tri + 0];
679 indices[realIndicesIndex + 1] = indices[tri + 1];
680 indices[realIndicesIndex + 2] = indices[tri + 2];
681 realIndicesIndex += 3;
682 }
683 }
684 }
685 DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
686 BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
687
688 if (realIndicesIndex != 0)
689 {
690 newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World,
691 realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
692 }
693 else
694 {
695 PhysicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
696 LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name);
697 }
698 } 285 }
286 else
287 {
288 // We don't need this reference to the mesh that is already being using.
289 potentialMesh.Dereference(m_physicsScene);
290 }
291 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1}", prim.LocalID, prim.PhysShape);
699 } 292 }
700 newShape.shapeKey = newMeshKey; 293 return ret;
701
702 return newShape;
703 }
704
705 // See that hull shape exists in the physical world and update prim.BSShape.
706 // We could be creating the hull because scale changed or whatever.
707 // Return 'true' if a new hull was built. Otherwise, returning a shared hull instance.
708 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
709 {
710 BulletShape newShape;
711
712 float lod;
713 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
714
715 // if the hull hasn't changed, don't rebuild it
716 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
717 return false;
718
719 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
720 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
721
722 // Remove usage of the previous shape.
723 DereferenceShape(prim.PhysShape, shapeCallback);
724
725 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
726 // It might not have been created if we're waiting for an asset.
727 newShape = VerifyMeshCreated(newShape, prim);
728
729 ReferenceShape(newShape);
730
731 prim.PhysShape = newShape;
732 return true; // 'true' means a new shape has been added to this prim
733 } 294 }
734 295
735 List<ConvexResult> m_hulls; 296 // Track another user of a body.
736 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 297 // We presume the caller has allocated the body.
298 // Bodies only have one user so the body is just put into the world if not already there.
299 private void ReferenceBody(BulletBody body)
737 { 300 {
738 301 lock (m_collectionActivityLock)
739 BulletShape newShape = new BulletShape();
740 IntPtr hullPtr = IntPtr.Zero;
741
742 HullDesc hullDesc;
743 if (Hulls.TryGetValue(newHullKey, out hullDesc))
744 {
745 // If the hull shape already has been created, just use the one shared instance.
746 newShape = hullDesc.shape.Clone();
747 }
748 else
749 { 302 {
750 // Build a new hull in the physical world. 303 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
751 // Pass true for physicalness as this prevents the creation of bounding box which is not needed 304 if (!m_physicsScene.PE.IsInWorld(m_physicsScene.World, body))
752 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
753 if (meshData != null)
754 { 305 {
755 306 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, body);
756 int[] indices = meshData.getIndexListAsInt(); 307 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
757 List<OMV.Vector3> vertices = meshData.getVertexList();
758
759 //format conversion from IMesh format to DecompDesc format
760 List<int> convIndices = new List<int>();
761 List<float3> convVertices = new List<float3>();
762 for (int ii = 0; ii < indices.GetLength(0); ii++)
763 {
764 convIndices.Add(indices[ii]);
765 }
766 foreach (OMV.Vector3 vv in vertices)
767 {
768 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
769 }
770
771 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
772 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
773 {
774 // Simple primitive shapes we know are convex so they are better implemented with
775 // fewer hulls.
776 // Check for simple shape (prim without cuts) and reduce split parameter if so.
777 if (PrimHasNoCuts(pbs))
778 {
779 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
780 }
781 }
782
783 // setup and do convex hull conversion
784 m_hulls = new List<ConvexResult>();
785 DecompDesc dcomp = new DecompDesc();
786 dcomp.mIndices = convIndices;
787 dcomp.mVertices = convVertices;
788 dcomp.mDepth = maxDepthSplit;
789 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
790 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
791 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
792 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
793 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
794 // create the hull into the _hulls variable
795 convexBuilder.process(dcomp);
796
797 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
798 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
799
800 // Convert the vertices and indices for passing to unmanaged.
801 // The hull information is passed as a large floating point array.
802 // The format is:
803 // convHulls[0] = number of hulls
804 // convHulls[1] = number of vertices in first hull
805 // convHulls[2] = hull centroid X coordinate
806 // convHulls[3] = hull centroid Y coordinate
807 // convHulls[4] = hull centroid Z coordinate
808 // convHulls[5] = first hull vertex X
809 // convHulls[6] = first hull vertex Y
810 // convHulls[7] = first hull vertex Z
811 // convHulls[8] = second hull vertex X
812 // ...
813 // convHulls[n] = number of vertices in second hull
814 // convHulls[n+1] = second hull centroid X coordinate
815 // ...
816 //
817 // TODO: is is very inefficient. Someday change the convex hull generator to return
818 // data structures that do not need to be converted in order to pass to Bullet.
819 // And maybe put the values directly into pinned memory rather than marshaling.
820 int hullCount = m_hulls.Count;
821 int totalVertices = 1; // include one for the count of the hulls
822 foreach (ConvexResult cr in m_hulls)
823 {
824 totalVertices += 4; // add four for the vertex count and centroid
825 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
826 }
827 float[] convHulls = new float[totalVertices];
828
829 convHulls[0] = (float)hullCount;
830 int jj = 1;
831 foreach (ConvexResult cr in m_hulls)
832 {
833 // copy vertices for index access
834 float3[] verts = new float3[cr.HullVertices.Count];
835 int kk = 0;
836 foreach (float3 ff in cr.HullVertices)
837 {
838 verts[kk++] = ff;
839 }
840
841 // add to the array one hull's worth of data
842 convHulls[jj++] = cr.HullIndices.Count;
843 convHulls[jj++] = 0f; // centroid x,y,z
844 convHulls[jj++] = 0f;
845 convHulls[jj++] = 0f;
846 foreach (int ind in cr.HullIndices)
847 {
848 convHulls[jj++] = verts[ind].x;
849 convHulls[jj++] = verts[ind].y;
850 convHulls[jj++] = verts[ind].z;
851 }
852 }
853 // create the hull data structure in Bullet
854 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
855 } 308 }
856 } 309 }
857
858 newShape.shapeKey = newHullKey;
859
860 return newShape;
861 }
862
863 // Callback from convex hull creater with a newly created hull.
864 // Just add it to our collection of hulls for this shape.
865 private void HullReturn(ConvexResult result)
866 {
867 m_hulls.Add(result);
868 return;
869 } 310 }
870 311
871 // Compound shapes are always built from scratch. 312 // Release the usage of a body.
872 // This shouldn't be to bad since most of the parts will be meshes that had been built previously. 313 // Called when releasing use of a BSBody. BSShape is handled separately.
873 private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 314 // Called in taint time.
874 { 315 public void DereferenceBody(BulletBody body, PhysicalDestructionCallback bodyCallback )
875 // Remove reference to the old shape
876 // Don't need to do this as the shape is freed when the new root shape is created below.
877 // DereferenceShape(prim.PhysShape, true, shapeCallback);
878
879 BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false);
880
881 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
882 CreateGeomMeshOrHull(prim, shapeCallback);
883 PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity);
884 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
885 prim.LocalID, cShape, prim.PhysShape);
886
887 prim.PhysShape = cShape;
888
889 return true;
890 }
891
892 // Create a hash of all the shape parameters to be used as a key
893 // for this particular shape.
894 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
895 {
896 // level of detail based on size and type of the object
897 float lod = BSParam.MeshLOD;
898
899 // prims with curvy internal cuts need higher lod
900 if (pbs.HollowShape == HollowShape.Circle)
901 lod = BSParam.MeshCircularLOD;
902
903 if (pbs.SculptEntry)
904 lod = BSParam.SculptLOD;
905
906 // Mega prims usually get more detail because one can interact with shape approximations at this size.
907 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
908 if (maxAxis > BSParam.MeshMegaPrimThreshold)
909 lod = BSParam.MeshMegaPrimLOD;
910
911 retLod = lod;
912 return pbs.GetMeshKey(size, lod);
913 }
914 // For those who don't want the LOD
915 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
916 { 316 {
917 float lod; 317 if (!body.HasPhysicalBody)
918 return ComputeShapeKey(size, pbs, out lod); 318 return;
919 }
920 319
921 // The creation of a mesh or hull can fail if an underlying asset is not available. 320 m_physicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
922 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
923 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
924 // The first case causes the asset to be fetched. The second case requires
925 // us to not loop forever.
926 // Called after creating a physical mesh or hull. If the physical shape was created,
927 // just return.
928 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
929 {
930 // If the shape was successfully created, nothing more to do
931 if (newShape.HasPhysicalShape)
932 return newShape;
933 321
934 // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been 322 lock (m_collectionActivityLock)
935 // fetched but we end up here again, the meshing of the asset must have failed.
936 // Prevent trying to keep fetching the mesh by declaring failure.
937 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
938 {
939 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
940 PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
941 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
942 }
943 else
944 { 323 {
945 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset 324 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
946 if (prim.BaseShape.SculptEntry 325 // If the caller needs to know the old body is going away, pass the event up.
947 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed 326 if (bodyCallback != null)
948 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting 327 bodyCallback(body, null);
949 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
950 )
951 {
952 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
953 // Multiple requestors will know we're waiting for this asset
954 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
955
956 BSPhysObject xprim = prim;
957 Util.FireAndForget(delegate
958 {
959 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
960 if (assetProvider != null)
961 {
962 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
963 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
964 {
965 bool assetFound = false;
966 string mismatchIDs = String.Empty; // DEBUG DEBUG
967 if (asset != null && yprim.BaseShape.SculptEntry)
968 {
969 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
970 {
971 yprim.BaseShape.SculptData = asset.Data;
972 // This will cause the prim to see that the filler shape is not the right
973 // one and try again to build the object.
974 // No race condition with the normal shape setting since the rebuild is at taint time.
975 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
976 assetFound = true;
977 }
978 else
979 {
980 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
981 }
982 }
983 if (assetFound)
984 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
985 else
986 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
987 DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
988 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
989 328
990 }); 329 // Removing an object not in the world is a NOOP
991 } 330 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, body);
992 else
993 {
994 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
995 PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
996 LogHeader, PhysicsScene.Name);
997 }
998 });
999 }
1000 else
1001 {
1002 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
1003 {
1004 PhysicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
1005 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
1006 }
1007 }
1008 }
1009 331
1010 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. 332 // Zero any reference to the shape so it is not freed when the body is deleted.
1011 BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); 333 m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, body, null);
1012 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
1013 334
1014 return fillinShape; 335 m_physicsScene.PE.DestroyObject(m_physicsScene.World, body);
336 }
1015 } 337 }
1016 338
1017 // Create a body object in Bullet. 339 // Create a body object in Bullet.
1018 // Updates prim.BSBody with the information about the new body if one is created. 340 // Updates prim.BSBody with the information about the new body if one is created.
1019 // Returns 'true' if an object was actually created. 341 // Returns 'true' if an object was actually created.
1020 // Called at taint-time. 342 // Called at taint-time.
1021 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BodyDestructionCallback bodyCallback) 343 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, PhysicalDestructionCallback bodyCallback)
1022 { 344 {
1023 bool ret = false; 345 bool ret = false;
1024 346
@@ -1029,7 +351,7 @@ public sealed class BSShapeCollection : IDisposable
1029 // If not a solid object, body is a GhostObject. Otherwise a RigidBody. 351 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
1030 if (!mustRebuild) 352 if (!mustRebuild)
1031 { 353 {
1032 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody); 354 CollisionObjectTypes bodyType = (CollisionObjectTypes)m_physicsScene.PE.GetBodyType(prim.PhysBody);
1033 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY 355 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
1034 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) 356 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
1035 { 357 {
@@ -1047,12 +369,12 @@ public sealed class BSShapeCollection : IDisposable
1047 BulletBody aBody; 369 BulletBody aBody;
1048 if (prim.IsSolid) 370 if (prim.IsSolid)
1049 { 371 {
1050 aBody = PhysicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); 372 aBody = m_physicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
1051 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody); 373 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,rigid,body={1}", prim.LocalID, aBody);
1052 } 374 }
1053 else 375 else
1054 { 376 {
1055 aBody = PhysicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); 377 aBody = m_physicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
1056 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); 378 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
1057 } 379 }
1058 380
@@ -1066,46 +388,10 @@ public sealed class BSShapeCollection : IDisposable
1066 return ret; 388 return ret;
1067 } 389 }
1068 390
1069 private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc)
1070 {
1071 bool ret = false;
1072 MeshDesc foundDesc = new MeshDesc();
1073 foreach (MeshDesc md in Meshes.Values)
1074 {
1075 if (md.shape.ReferenceSame(shape))
1076 {
1077 foundDesc = md;
1078 ret = true;
1079 break;
1080 }
1081
1082 }
1083 outDesc = foundDesc;
1084 return ret;
1085 }
1086
1087 private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc)
1088 {
1089 bool ret = false;
1090 HullDesc foundDesc = new HullDesc();
1091 foreach (HullDesc hd in Hulls.Values)
1092 {
1093 if (hd.shape.ReferenceSame(shape))
1094 {
1095 foundDesc = hd;
1096 ret = true;
1097 break;
1098 }
1099
1100 }
1101 outDesc = foundDesc;
1102 return ret;
1103 }
1104
1105 private void DetailLog(string msg, params Object[] args) 391 private void DetailLog(string msg, params Object[] args)
1106 { 392 {
1107 if (PhysicsScene.PhysicsLogging.Enabled) 393 if (m_physicsScene.PhysicsLogging.Enabled)
1108 PhysicsScene.DetailLog(msg, args); 394 m_physicsScene.DetailLog(msg, args);
1109 } 395 }
1110} 396}
1111} 397}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index ee18379..fe5ff6c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -29,115 +29,312 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31 31
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.Meshing;
35using OpenSim.Region.Physics.ConvexDecompositionDotNet;
36
32using OMV = OpenMetaverse; 37using OMV = OpenMetaverse;
33 38
34namespace OpenSim.Region.Physics.BulletSPlugin 39namespace OpenSim.Region.Physics.BulletSPlugin
35{ 40{
36public abstract class BSShape 41public abstract class BSShape
37{ 42{
43 private static string LogHeader = "[BULLETSIM SHAPE]";
44
38 public int referenceCount { get; set; } 45 public int referenceCount { get; set; }
39 public DateTime lastReferenced { get; set; } 46 public DateTime lastReferenced { get; set; }
47 public BulletShape physShapeInfo { get; set; }
40 48
41 public BSShape() 49 public BSShape()
42 { 50 {
43 referenceCount = 0; 51 referenceCount = 1;
44 lastReferenced = DateTime.Now; 52 lastReferenced = DateTime.Now;
53 physShapeInfo = new BulletShape();
45 } 54 }
46 55 public BSShape(BulletShape pShape)
47 // Get a reference to a physical shape. Create if it doesn't exist
48 public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
49 { 56 {
50 BSShape ret = null; 57 referenceCount = 1;
51 58 lastReferenced = DateTime.Now;
52 if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) 59 physShapeInfo = pShape;
53 { 60 }
54 // an avatar capsule is close to a native shape (it is not shared)
55 ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
56 FixedShapeKey.KEY_CAPSULE);
57 physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
58 }
59
60 // Compound shapes are handled special as they are rebuilt from scratch.
61 // This isn't too great a hardship since most of the child shapes will have already been created.
62 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
63 {
64 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
65 ret = BSShapeCompound.GetReference(prim);
66 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
67 }
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 61
77 if (ret == null) 62 // Get another reference to this shape.
78 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); 63 public abstract BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim);
79 64
80 return ret; 65 // Called when this shape is being used again.
81 } 66 // Used internally. External callers should call instance.GetReference() to properly copy/reference
82 public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 67 // the shape.
68 protected virtual void IncrementReference()
83 { 69 {
84 return null; 70 referenceCount++;
71 lastReferenced = DateTime.Now;
85 } 72 }
86 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 73
74 // Called when this shape is done being used.
75 protected virtual void DecrementReference()
87 { 76 {
88 return null; 77 referenceCount--;
78 lastReferenced = DateTime.Now;
89 } 79 }
90 80
91 // Release the use of a physical shape. 81 // Release the use of a physical shape.
92 public abstract void Dereference(BSScene physicsScene); 82 public abstract void Dereference(BSScene physicsScene);
93 83
94 // All shapes have a static call to get a reference to the physical shape 84 // Return 'true' if there is an allocated physics physical shape under this class instance.
95 // protected abstract static BSShape GetReference(); 85 public virtual bool HasPhysicalShape
86 {
87 get
88 {
89 if (physShapeInfo != null)
90 return physShapeInfo.HasPhysicalShape;
91 return false;
92 }
93 }
94 public virtual BSPhysicsShapeType ShapeType
95 {
96 get
97 {
98 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
99 if (physShapeInfo != null && physShapeInfo.HasPhysicalShape)
100 ret = physShapeInfo.shapeType;
101 return ret;
102 }
103 }
96 104
97 // Returns a string for debugging that uniquily identifies the memory used by this instance 105 // Returns a string for debugging that uniquily identifies the memory used by this instance
98 public virtual string AddrString 106 public virtual string AddrString
99 { 107 {
100 get { return "unknown"; } 108 get
109 {
110 if (physShapeInfo != null)
111 return physShapeInfo.AddrString;
112 return "unknown";
113 }
101 } 114 }
102 115
103 public override string ToString() 116 public override string ToString()
104 { 117 {
105 StringBuilder buff = new StringBuilder(); 118 StringBuilder buff = new StringBuilder();
106 buff.Append("<p="); 119 if (physShapeInfo == null)
107 buff.Append(AddrString); 120 {
121 buff.Append("<noPhys");
122 }
123 else
124 {
125 buff.Append("<phy=");
126 buff.Append(physShapeInfo.ToString());
127 }
108 buff.Append(",c="); 128 buff.Append(",c=");
109 buff.Append(referenceCount.ToString()); 129 buff.Append(referenceCount.ToString());
110 buff.Append(">"); 130 buff.Append(">");
111 return buff.ToString(); 131 return buff.ToString();
112 } 132 }
133
134 #region Common shape routines
135 // Create a hash of all the shape parameters to be used as a key for this particular shape.
136 public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
137 {
138 // level of detail based on size and type of the object
139 float lod = BSParam.MeshLOD;
140 if (pbs.SculptEntry)
141 lod = BSParam.SculptLOD;
142
143 // Mega prims usually get more detail because one can interact with shape approximations at this size.
144 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
145 if (maxAxis > BSParam.MeshMegaPrimThreshold)
146 lod = BSParam.MeshMegaPrimLOD;
147
148 retLod = lod;
149 return pbs.GetMeshKey(size, lod);
150 }
151
152 // The creation of a mesh or hull can fail if an underlying asset is not available.
153 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
154 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
155 // The first case causes the asset to be fetched. The second case requires
156 // us to not loop forever.
157 // Called after creating a physical mesh or hull. If the physical shape was created,
158 // just return.
159 public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
160 {
161 // If the shape was successfully created, nothing more to do
162 if (newShape.HasPhysicalShape)
163 return newShape;
164
165 // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
166 // fetched but we end up here again, the meshing of the asset must have failed.
167 // Prevent trying to keep fetching the mesh by declaring failure.
168 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
169 {
170 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedMeshing;
171 physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. prim={1}, texture={2}",
172 LogHeader, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
173 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,setFailed,prim={1},tex={2}",
174 prim.LocalID, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
175 }
176 else
177 {
178 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
179 if (prim.BaseShape.SculptEntry
180 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.FailedAssetFetch
181 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.FailedMeshing
182 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
183 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
184 )
185 {
186 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,fetchAsset,objNam={1},tex={2}",
187 prim.LocalID, prim.PhysObjectName, prim.BaseShape.SculptTexture);
188 // Multiple requestors will know we're waiting for this asset
189 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
190
191 BSPhysObject xprim = prim;
192 Util.FireAndForget(delegate
193 {
194 // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,inFireAndForget", xprim.LocalID);
195 RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
196 if (assetProvider != null)
197 {
198 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
199 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
200 {
201 // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,assetProviderCallback", xprim.LocalID);
202 bool assetFound = false;
203 string mismatchIDs = String.Empty; // DEBUG DEBUG
204 if (asset != null && yprim.BaseShape.SculptEntry)
205 {
206 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
207 {
208 yprim.BaseShape.SculptData = asset.Data;
209 // This will cause the prim to see that the filler shape is not the right
210 // one and try again to build the object.
211 // No race condition with the normal shape setting since the rebuild is at taint time.
212 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
213 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
214 assetFound = true;
215 }
216 else
217 {
218 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
219 }
220 }
221 if (!assetFound)
222 {
223 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedAssetFetch;
224 }
225 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
226 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
227 });
228 }
229 else
230 {
231 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedAssetFetch;
232 physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
233 LogHeader, physicsScene.Name);
234 }
235 });
236 }
237 else
238 {
239 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedAssetFetch)
240 {
241 physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. prim={1}, texture={2}",
242 LogHeader, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
243 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,wasFailed,prim={1},tex={2}",
244 prim.LocalID, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
245 }
246 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedMeshing)
247 {
248 physicsScene.Logger.WarnFormat("{0} Mesh asset would not mesh. prim={1}, texture={2}",
249 LogHeader, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
250 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,wasFailedMeshing,prim={1},tex={2}",
251 prim.LocalID, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
252 }
253 }
254 }
255
256 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
257 BSShape fillShape = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
258 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,boxTempShape", prim.LocalID);
259
260 return fillShape.physShapeInfo;
261 }
262
263 public static String UsefulPrimInfo(BSScene pScene, BSPhysObject prim)
264 {
265 StringBuilder buff = new StringBuilder(prim.PhysObjectName);
266 buff.Append("/pos=");
267 buff.Append(prim.RawPosition.ToString());
268 if (pScene != null)
269 {
270 buff.Append("/rgn=");
271 buff.Append(pScene.Name);
272 }
273 return buff.ToString();
274 }
275
276 #endregion // Common shape routines
113} 277}
114 278
279// ============================================================================================================
115public class BSShapeNull : BSShape 280public class BSShapeNull : BSShape
116{ 281{
117 public BSShapeNull() : base() 282 public BSShapeNull() : base()
118 { 283 {
119 } 284 }
120 public static BSShape GetReference() { return new BSShapeNull(); } 285 public static BSShape GetReference() { return new BSShapeNull(); }
286 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim) { return new BSShapeNull(); }
121 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } 287 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
122} 288}
123 289
290// ============================================================================================================
124public class BSShapeNative : BSShape 291public class BSShapeNative : BSShape
125{ 292{
126 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]"; 293 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
127 public BSShapeNative() : base() 294 public BSShapeNative(BulletShape pShape) : base(pShape)
128 { 295 {
129 } 296 }
130 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, 297
131 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) 298 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
299 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
132 { 300 {
133 // Native shapes are not shared and are always built anew. 301 // Native shapes are not shared and are always built anew.
134 //return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); 302 return new BSShapeNative(CreatePhysicalNativeShape(physicsScene, prim, shapeType, shapeKey));
135 return null;
136 } 303 }
137 304
138 private BSShapeNative(BSScene physicsScene, BSPhysObject prim, 305 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
139 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
140 { 306 {
307 // Native shapes are not shared so we return a new shape.
308 BSShape ret = null;
309 lock (physShapeInfo)
310 {
311 ret = new BSShapeNative(CreatePhysicalNativeShape(pPhysicsScene, pPrim,
312 physShapeInfo.shapeType, (FixedShapeKey)physShapeInfo.shapeKey));
313 }
314 return ret;
315 }
316
317 // Make this reference to the physical shape go away since native shapes are not shared.
318 public override void Dereference(BSScene physicsScene)
319 {
320 // Native shapes are not tracked and are released immediately
321 lock (physShapeInfo)
322 {
323 if (physShapeInfo.HasPhysicalShape)
324 {
325 physicsScene.DetailLog("{0},BSShapeNative.Dereference,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
326 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
327 }
328 physShapeInfo.Clear();
329 // Garbage collection will free up this instance.
330 }
331 }
332
333 private static BulletShape CreatePhysicalNativeShape(BSScene physicsScene, BSPhysObject prim,
334 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
335 {
336 BulletShape newShape;
337
141 ShapeData nativeShapeData = new ShapeData(); 338 ShapeData nativeShapeData = new ShapeData();
142 nativeShapeData.Type = shapeType; 339 nativeShapeData.Type = shapeType;
143 nativeShapeData.ID = prim.LocalID; 340 nativeShapeData.ID = prim.LocalID;
@@ -146,84 +343,880 @@ public class BSShapeNative : BSShape
146 nativeShapeData.MeshKey = (ulong)shapeKey; 343 nativeShapeData.MeshKey = (ulong)shapeKey;
147 nativeShapeData.HullKey = (ulong)shapeKey; 344 nativeShapeData.HullKey = (ulong)shapeKey;
148 345
149
150 /*
151 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) 346 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
152 { 347 {
153 ptr = PhysicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale); 348 newShape = physicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale);
154 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 349 physicsScene.DetailLog("{0},BSShapeNative,capsule,scale={1}", prim.LocalID, prim.Scale);
155 } 350 }
156 else 351 else
157 { 352 {
158 ptr = PhysicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData); 353 newShape = physicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData);
159 } 354 }
160 if (ptr == IntPtr.Zero) 355 if (!newShape.HasPhysicalShape)
161 { 356 {
162 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 357 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
163 LogHeader, prim.LocalID, shapeType); 358 LogHeader, prim.LocalID, shapeType);
164 } 359 }
165 type = shapeType; 360 newShape.shapeType = shapeType;
166 key = (UInt64)shapeKey; 361 newShape.isNativeShape = true;
167 */ 362 newShape.shapeKey = (UInt64)shapeKey;
168 } 363 return newShape;
169 // Make this reference to the physical shape go away since native shapes are not shared.
170 public override void Dereference(BSScene physicsScene)
171 {
172 /*
173 // Native shapes are not tracked and are released immediately
174 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
175 PhysicsScene.PE.DeleteCollisionShape(physicsScene.World, this);
176 ptr = IntPtr.Zero;
177 // Garbage collection will free up this instance.
178 */
179 } 364 }
365
180} 366}
181 367
368// ============================================================================================================
182public class BSShapeMesh : BSShape 369public class BSShapeMesh : BSShape
183{ 370{
184 private static string LogHeader = "[BULLETSIM SHAPE MESH]"; 371 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
185 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>(); 372 public static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
186 373
187 public BSShapeMesh() : base() 374 public BSShapeMesh(BulletShape pShape) : base(pShape)
188 { 375 {
189 } 376 }
190 public static BSShape GetReference() { return new BSShapeNull(); } 377 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
191 public override void Dereference(BSScene physicsScene) { } 378 {
379 float lod;
380 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
381
382 BSShapeMesh retMesh = null;
383 lock (Meshes)
384 {
385 if (Meshes.TryGetValue(newMeshKey, out retMesh))
386 {
387 // The mesh has already been created. Return a new reference to same.
388 retMesh.IncrementReference();
389 }
390 else
391 {
392 retMesh = new BSShapeMesh(new BulletShape());
393 // An instance of this mesh has not been created. Build and remember same.
394 BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
395
396 // Check to see if mesh was created (might require an asset).
397 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
398 if (!newShape.isNativeShape
399 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedMeshing
400 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedAssetFetch)
401 {
402 // If a mesh was what was created, remember the built shape for later sharing.
403 // Also note that if meshing failed we put it in the mesh list as there is nothing else to do about the mesh.
404 Meshes.Add(newMeshKey, retMesh);
405 }
406
407 retMesh.physShapeInfo = newShape;
408 }
409 }
410 physicsScene.DetailLog("{0},BSShapeMesh,getReference,mesh={1},size={2},lod={3}", prim.LocalID, retMesh, prim.Size, lod);
411 return retMesh;
412 }
413 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
414 {
415 BSShape ret = null;
416 // If the underlying shape is native, the actual shape has not been build (waiting for asset)
417 // and we must create a copy of the native shape since they are never shared.
418 if (physShapeInfo.HasPhysicalShape && physShapeInfo.isNativeShape)
419 {
420 // TODO: decide when the native shapes should be freed. Check in Dereference?
421 ret = BSShapeNative.GetReference(pPhysicsScene, pPrim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
422 }
423 else
424 {
425 // Another reference to this shape is just counted.
426 IncrementReference();
427 ret = this;
428 }
429 return ret;
430 }
431 public override void Dereference(BSScene physicsScene)
432 {
433 lock (Meshes)
434 {
435 this.DecrementReference();
436 physicsScene.DetailLog("{0},BSShapeMesh.Dereference,shape={1}", BSScene.DetailLogZero, this);
437 // TODO: schedule aging and destruction of unused meshes.
438 }
439 }
440 // Loop through all the known meshes and return the description based on the physical address.
441 public static bool TryGetMeshByPtr(BulletShape pShape, out BSShapeMesh outMesh)
442 {
443 bool ret = false;
444 BSShapeMesh foundDesc = null;
445 lock (Meshes)
446 {
447 foreach (BSShapeMesh sm in Meshes.Values)
448 {
449 if (sm.physShapeInfo.ReferenceSame(pShape))
450 {
451 foundDesc = sm;
452 ret = true;
453 break;
454 }
455
456 }
457 }
458 outMesh = foundDesc;
459 return ret;
460 }
461
462 public delegate BulletShape CreateShapeCall(BulletWorld world, int indicesCount, int[] indices, int verticesCount, float[] vertices );
463 private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
464 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
465 {
466 return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
467 (w, iC, i, vC, v) => physicsScene.PE.CreateMeshShape(w, iC, i, vC, v) );
468 }
469
470 // Code that uses the mesher to create the index/vertices info for a trimesh shape.
471 // This is used by the passed 'makeShape' call to create the Bullet mesh shape.
472 // The actual build call is passed so this logic can be used by several of the shapes that use a
473 // simple mesh as their base shape.
474 public static BulletShape CreatePhysicalMeshShape(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
475 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod, CreateShapeCall makeShape)
476 {
477 BulletShape newShape = new BulletShape();
478
479 IMesh meshData = null;
480 lock (physicsScene.mesher)
481 {
482 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
483 false, // say it is not physical so a bounding box is not built
484 false, // do not cache the mesh and do not use previously built versions
485 false,
486 false
487 );
488 }
489
490 if (meshData != null)
491 {
492 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
493 {
494 // Release the fetched asset data once it has been used.
495 pbs.SculptData = new byte[0];
496 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
497 }
498
499 int[] indices = meshData.getIndexListAsInt();
500 int realIndicesIndex = indices.Length;
501 float[] verticesAsFloats = meshData.getVertexListAsFloat();
502
503 if (BSParam.ShouldRemoveZeroWidthTriangles)
504 {
505 // Remove degenerate triangles. These are triangles with two of the vertices
506 // are the same. This is complicated by the problem that vertices are not
507 // made unique in sculpties so we have to compare the values in the vertex.
508 realIndicesIndex = 0;
509 for (int tri = 0; tri < indices.Length; tri += 3)
510 {
511 // Compute displacements into vertex array for each vertex of the triangle
512 int v1 = indices[tri + 0] * 3;
513 int v2 = indices[tri + 1] * 3;
514 int v3 = indices[tri + 2] * 3;
515 // Check to see if any two of the vertices are the same
516 if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
517 && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
518 && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
519 || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
520 && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
521 && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
522 || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
523 && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
524 && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
525 )
526 {
527 // None of the vertices of the triangles are the same. This is a good triangle;
528 indices[realIndicesIndex + 0] = indices[tri + 0];
529 indices[realIndicesIndex + 1] = indices[tri + 1];
530 indices[realIndicesIndex + 2] = indices[tri + 2];
531 realIndicesIndex += 3;
532 }
533 }
534 }
535 physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,key={1},origTri={2},realTri={3},numVerts={4}",
536 BSScene.DetailLogZero, newMeshKey.ToString("X"), indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
537
538 if (realIndicesIndex != 0)
539 {
540 newShape = makeShape(physicsScene.World, realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
541 }
542 else
543 {
544 // Force the asset condition to 'failed' so we won't try to keep fetching and processing this mesh.
545 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedMeshing;
546 physicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim={1}", LogHeader, UsefulPrimInfo(physicsScene, prim) );
547 physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,allDegenerate,key={1}", prim.LocalID, newMeshKey);
548 }
549 }
550 newShape.shapeKey = newMeshKey;
551
552 return newShape;
553 }
192} 554}
193 555
556// ============================================================================================================
194public class BSShapeHull : BSShape 557public class BSShapeHull : BSShape
195{ 558{
196 private static string LogHeader = "[BULLETSIM SHAPE HULL]"; 559 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
197 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>(); 560 public static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
198 561
199 public BSShapeHull() : base() 562 public BSShapeHull(BulletShape pShape) : base(pShape)
200 { 563 {
201 } 564 }
202 public static BSShape GetReference() { return new BSShapeNull(); } 565 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
203 public override void Dereference(BSScene physicsScene) { } 566 {
567 float lod;
568 System.UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
569
570 BSShapeHull retHull = null;
571 lock (Hulls)
572 {
573 if (Hulls.TryGetValue(newHullKey, out retHull))
574 {
575 // The mesh has already been created. Return a new reference to same.
576 retHull.IncrementReference();
577 }
578 else
579 {
580 retHull = new BSShapeHull(new BulletShape());
581 // An instance of this mesh has not been created. Build and remember same.
582 BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod);
583
584 // Check to see if hull was created (might require an asset).
585 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
586 if (!newShape.isNativeShape
587 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedMeshing
588 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedAssetFetch)
589 {
590 // If a mesh was what was created, remember the built shape for later sharing.
591 Hulls.Add(newHullKey, retHull);
592 }
593 retHull.physShapeInfo = newShape;
594 }
595 }
596 physicsScene.DetailLog("{0},BSShapeHull,getReference,hull={1},size={2},lod={3}", prim.LocalID, retHull, prim.Size, lod);
597 return retHull;
598 }
599 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
600 {
601 BSShape ret = null;
602 // If the underlying shape is native, the actual shape has not been build (waiting for asset)
603 // and we must create a copy of the native shape since they are never shared.
604 if (physShapeInfo.HasPhysicalShape && physShapeInfo.isNativeShape)
605 {
606 // TODO: decide when the native shapes should be freed. Check in Dereference?
607 ret = BSShapeNative.GetReference(pPhysicsScene, pPrim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
608 }
609 else
610 {
611 // Another reference to this shape is just counted.
612 IncrementReference();
613 ret = this;
614 }
615 return ret;
616 }
617 public override void Dereference(BSScene physicsScene)
618 {
619 lock (Hulls)
620 {
621 this.DecrementReference();
622 physicsScene.DetailLog("{0},BSShapeHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
623 // TODO: schedule aging and destruction of unused meshes.
624 }
625 }
626 List<ConvexResult> m_hulls;
627 private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
628 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
629 {
630 BulletShape newShape = new BulletShape();
631
632 IMesh meshData = null;
633 List<List<OMV.Vector3>> allHulls = null;
634 lock (physicsScene.mesher)
635 {
636 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
637 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false);
638
639 // If we should use the asset's hull info, fetch it out of the locked mesher
640 if (meshData != null && BSParam.ShouldUseAssetHulls)
641 {
642 Meshmerizer realMesher = physicsScene.mesher as Meshmerizer;
643 if (realMesher != null)
644 {
645 allHulls = realMesher.GetConvexHulls(size);
646 }
647 if (allHulls == null)
648 {
649 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,noAssetHull", prim.LocalID);
650 }
651 }
652 }
653
654 // If there is hull data in the mesh asset, build the hull from that
655 if (allHulls != null && BSParam.ShouldUseAssetHulls)
656 {
657 int hullCount = allHulls.Count;
658 int totalVertices = 1; // include one for the count of the hulls
659 // Using the structure described for HACD hulls, create the memory sturcture
660 // to pass the hull data to the creater.
661 foreach (List<OMV.Vector3> hullVerts in allHulls)
662 {
663 totalVertices += 4; // add four for the vertex count and centroid
664 totalVertices += hullVerts.Count * 3; // one vertex is three dimensions
665 }
666 float[] convHulls = new float[totalVertices];
667
668 convHulls[0] = (float)hullCount;
669 int jj = 1;
670 foreach (List<OMV.Vector3> hullVerts in allHulls)
671 {
672 convHulls[jj + 0] = hullVerts.Count;
673 convHulls[jj + 1] = 0f; // centroid x,y,z
674 convHulls[jj + 2] = 0f;
675 convHulls[jj + 3] = 0f;
676 jj += 4;
677 foreach (OMV.Vector3 oneVert in hullVerts)
678 {
679 convHulls[jj + 0] = oneVert.X;
680 convHulls[jj + 1] = oneVert.Y;
681 convHulls[jj + 2] = oneVert.Z;
682 jj += 3;
683 }
684 }
685
686 // create the hull data structure in Bullet
687 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
688
689 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,hulls={1},totVert={2},shape={3}",
690 prim.LocalID, hullCount, totalVertices, newShape);
691 }
692
693 // If no hull specified in the asset and we should use Bullet's HACD approximation...
694 if (!newShape.HasPhysicalShape && BSParam.ShouldUseBulletHACD)
695 {
696 // Build the hull shape from an existing mesh shape.
697 // The mesh should have already been created in Bullet.
698 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,entry", prim.LocalID);
699 BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);
700
701 if (meshShape.physShapeInfo.HasPhysicalShape)
702 {
703 HACDParams parms;
704 parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
705 parms.minClusters = BSParam.BHullMinClusters;
706 parms.compacityWeight = BSParam.BHullCompacityWeight;
707 parms.volumeWeight = BSParam.BHullVolumeWeight;
708 parms.concavity = BSParam.BHullConcavity;
709 parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
710 parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
711 parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
712 parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
713
714 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
715 newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
716 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,shape={1}", prim.LocalID, newShape);
717
718 // Now done with the mesh shape.
719 meshShape.Dereference(physicsScene);
720 }
721 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
722 }
723
724 // If no other hull specifications, use our HACD hull approximation.
725 if (!newShape.HasPhysicalShape && meshData != null)
726 {
727 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
728 {
729 // Release the fetched asset data once it has been used.
730 pbs.SculptData = new byte[0];
731 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
732 }
733
734 int[] indices = meshData.getIndexListAsInt();
735 List<OMV.Vector3> vertices = meshData.getVertexList();
736
737 //format conversion from IMesh format to DecompDesc format
738 List<int> convIndices = new List<int>();
739 List<float3> convVertices = new List<float3>();
740 for (int ii = 0; ii < indices.GetLength(0); ii++)
741 {
742 convIndices.Add(indices[ii]);
743 }
744 foreach (OMV.Vector3 vv in vertices)
745 {
746 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
747 }
748
749 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
750 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
751 {
752 // Simple primitive shapes we know are convex so they are better implemented with
753 // fewer hulls.
754 // Check for simple shape (prim without cuts) and reduce split parameter if so.
755 if (BSShapeCollection.PrimHasNoCuts(pbs))
756 {
757 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
758 }
759 }
760
761 // setup and do convex hull conversion
762 m_hulls = new List<ConvexResult>();
763 DecompDesc dcomp = new DecompDesc();
764 dcomp.mIndices = convIndices;
765 dcomp.mVertices = convVertices;
766 dcomp.mDepth = maxDepthSplit;
767 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
768 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
769 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
770 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
771 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
772 // create the hull into the _hulls variable
773 convexBuilder.process(dcomp);
774
775 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
776 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
777
778 // Convert the vertices and indices for passing to unmanaged.
779 // The hull information is passed as a large floating point array.
780 // The format is:
781 // convHulls[0] = number of hulls
782 // convHulls[1] = number of vertices in first hull
783 // convHulls[2] = hull centroid X coordinate
784 // convHulls[3] = hull centroid Y coordinate
785 // convHulls[4] = hull centroid Z coordinate
786 // convHulls[5] = first hull vertex X
787 // convHulls[6] = first hull vertex Y
788 // convHulls[7] = first hull vertex Z
789 // convHulls[8] = second hull vertex X
790 // ...
791 // convHulls[n] = number of vertices in second hull
792 // convHulls[n+1] = second hull centroid X coordinate
793 // ...
794 //
795 // TODO: is is very inefficient. Someday change the convex hull generator to return
796 // data structures that do not need to be converted in order to pass to Bullet.
797 // And maybe put the values directly into pinned memory rather than marshaling.
798 int hullCount = m_hulls.Count;
799 int totalVertices = 1; // include one for the count of the hulls
800 foreach (ConvexResult cr in m_hulls)
801 {
802 totalVertices += 4; // add four for the vertex count and centroid
803 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
804 }
805 float[] convHulls = new float[totalVertices];
806
807 convHulls[0] = (float)hullCount;
808 int jj = 1;
809 foreach (ConvexResult cr in m_hulls)
810 {
811 // copy vertices for index access
812 float3[] verts = new float3[cr.HullVertices.Count];
813 int kk = 0;
814 foreach (float3 ff in cr.HullVertices)
815 {
816 verts[kk++] = ff;
817 }
818
819 // add to the array one hull's worth of data
820 convHulls[jj++] = cr.HullIndices.Count;
821 convHulls[jj++] = 0f; // centroid x,y,z
822 convHulls[jj++] = 0f;
823 convHulls[jj++] = 0f;
824 foreach (int ind in cr.HullIndices)
825 {
826 convHulls[jj++] = verts[ind].x;
827 convHulls[jj++] = verts[ind].y;
828 convHulls[jj++] = verts[ind].z;
829 }
830 }
831 // create the hull data structure in Bullet
832 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
833 }
834 newShape.shapeKey = newHullKey;
835 return newShape;
836 }
837 // Callback from convex hull creater with a newly created hull.
838 // Just add it to our collection of hulls for this shape.
839 private void HullReturn(ConvexResult result)
840 {
841 m_hulls.Add(result);
842 return;
843 }
844 // Loop through all the known hulls and return the description based on the physical address.
845 public static bool TryGetHullByPtr(BulletShape pShape, out BSShapeHull outHull)
846 {
847 bool ret = false;
848 BSShapeHull foundDesc = null;
849 lock (Hulls)
850 {
851 foreach (BSShapeHull sh in Hulls.Values)
852 {
853 if (sh.physShapeInfo.ReferenceSame(pShape))
854 {
855 foundDesc = sh;
856 ret = true;
857 break;
858 }
859
860 }
861 }
862 outHull = foundDesc;
863 return ret;
864 }
204} 865}
205 866
867// ============================================================================================================
206public class BSShapeCompound : BSShape 868public class BSShapeCompound : BSShape
207{ 869{
208 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; 870 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
209 public BSShapeCompound() : base() 871 public static Dictionary<string, BSShapeCompound> CompoundShapes = new Dictionary<string, BSShapeCompound>();
872
873 public BSShapeCompound(BulletShape pShape) : base(pShape)
210 { 874 {
211 } 875 }
212 public static BSShape GetReference(BSPhysObject prim) 876 public static BSShape GetReference(BSScene physicsScene)
213 { 877 {
214 return new BSShapeNull(); 878 // Base compound shapes are not shared so this returns a raw shape.
879 // A built compound shape can be reused in linksets.
880 BSShapeCompound ret = new BSShapeCompound(CreatePhysicalCompoundShape(physicsScene));
881 CompoundShapes.Add(ret.AddrString, ret);
882 return ret;
883 }
884 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
885 {
886 // Calling this reference means we want another handle to an existing compound shape
887 // (usually linksets) so return this copy.
888 IncrementReference();
889 return this;
890 }
891 // Dereferencing a compound shape releases the hold on all the child shapes.
892 public override void Dereference(BSScene physicsScene)
893 {
894 lock (physShapeInfo)
895 {
896 this.DecrementReference();
897 physicsScene.DetailLog("{0},BSShapeCompound.Dereference,shape={1}", BSScene.DetailLogZero, this);
898 if (referenceCount <= 0)
899 {
900 if (!physicsScene.PE.IsCompound(physShapeInfo))
901 {
902 // Failed the sanity check!!
903 physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
904 LogHeader, physShapeInfo.shapeType, physShapeInfo.AddrString);
905 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
906 BSScene.DetailLogZero, physShapeInfo.shapeType, physShapeInfo.AddrString);
907 return;
908 }
909
910 int numChildren = physicsScene.PE.GetNumberOfCompoundChildren(physShapeInfo);
911 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}",
912 BSScene.DetailLogZero, physShapeInfo, numChildren);
913
914 // Loop through all the children dereferencing each.
915 for (int ii = numChildren - 1; ii >= 0; ii--)
916 {
917 BulletShape childShape = physicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(physShapeInfo, ii);
918 DereferenceAnonCollisionShape(physicsScene, childShape);
919 }
920
921 lock (CompoundShapes)
922 CompoundShapes.Remove(physShapeInfo.AddrString);
923 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
924 }
925 }
926 }
927 public static bool TryGetCompoundByPtr(BulletShape pShape, out BSShapeCompound outCompound)
928 {
929 lock (CompoundShapes)
930 {
931 string addr = pShape.AddrString;
932 return CompoundShapes.TryGetValue(addr, out outCompound);
933 }
934 }
935 private static BulletShape CreatePhysicalCompoundShape(BSScene physicsScene)
936 {
937 BulletShape cShape = physicsScene.PE.CreateCompoundShape(physicsScene.World, false);
938 return cShape;
939 }
940 // Sometimes we have a pointer to a collision shape but don't know what type it is.
941 // Figure out type and call the correct dereference routine.
942 // Called at taint-time.
943 private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape)
944 {
945 // TODO: figure a better way to go through all the shape types and find a possible instance.
946 physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,shape={1}",
947 BSScene.DetailLogZero, pShape);
948 BSShapeMesh meshDesc;
949 if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
950 {
951 meshDesc.Dereference(physicsScene);
952 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,foundMesh,shape={1}", BSScene.DetailLogZero, pShape);
953 }
954 else
955 {
956 BSShapeHull hullDesc;
957 if (BSShapeHull.TryGetHullByPtr(pShape, out hullDesc))
958 {
959 hullDesc.Dereference(physicsScene);
960 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,foundHull,shape={1}", BSScene.DetailLogZero, pShape);
961 }
962 else
963 {
964 BSShapeConvexHull chullDesc;
965 if (BSShapeConvexHull.TryGetConvexHullByPtr(pShape, out chullDesc))
966 {
967 chullDesc.Dereference(physicsScene);
968 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,foundConvexHull,shape={1}", BSScene.DetailLogZero, pShape);
969 }
970 else
971 {
972 BSShapeGImpact gImpactDesc;
973 if (BSShapeGImpact.TryGetGImpactByPtr(pShape, out gImpactDesc))
974 {
975 gImpactDesc.Dereference(physicsScene);
976 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,foundgImpact,shape={1}", BSScene.DetailLogZero, pShape);
977 }
978 else
979 {
980 // Didn't find it in the lists of specific types. It could be compound.
981 BSShapeCompound compoundDesc;
982 if (BSShapeCompound.TryGetCompoundByPtr(pShape, out compoundDesc))
983 {
984 compoundDesc.Dereference(physicsScene);
985 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,recursiveCompoundShape,shape={1}", BSScene.DetailLogZero, pShape);
986 }
987 else
988 {
989 // If none of the above, maybe it is a simple native shape.
990 if (physicsScene.PE.IsNativeShape(pShape))
991 {
992 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,assumingNative,shape={1}", BSScene.DetailLogZero, pShape);
993 BSShapeNative nativeShape = new BSShapeNative(pShape);
994 nativeShape.Dereference(physicsScene);
995 }
996 }
997 }
998 }
999 }
1000 }
1001 }
1002}
1003
1004// ============================================================================================================
1005public class BSShapeConvexHull : BSShape
1006{
1007 private static string LogHeader = "[BULLETSIM SHAPE CONVEX HULL]";
1008 public static Dictionary<System.UInt64, BSShapeConvexHull> ConvexHulls = new Dictionary<System.UInt64, BSShapeConvexHull>();
1009
1010 public BSShapeConvexHull(BulletShape pShape) : base(pShape)
1011 {
1012 }
1013 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
1014 {
1015 float lod;
1016 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
1017
1018 physicsScene.DetailLog("{0},BSShapeConvexHull,getReference,newKey={1},size={2},lod={3}",
1019 prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
1020
1021 BSShapeConvexHull retConvexHull = null;
1022 lock (ConvexHulls)
1023 {
1024 if (ConvexHulls.TryGetValue(newMeshKey, out retConvexHull))
1025 {
1026 // The mesh has already been created. Return a new reference to same.
1027 retConvexHull.IncrementReference();
1028 }
1029 else
1030 {
1031 retConvexHull = new BSShapeConvexHull(new BulletShape());
1032 BulletShape convexShape = null;
1033
1034 // Get a handle to a mesh to build the hull from
1035 BSShape baseMesh = BSShapeMesh.GetReference(physicsScene, false /* forceRebuild */, prim);
1036 if (baseMesh.physShapeInfo.isNativeShape)
1037 {
1038 // We get here if the mesh was not creatable. Could be waiting for an asset from the disk.
1039 // In the short term, we return the native shape and a later ForceBodyShapeRebuild should
1040 // get back to this code with a buildable mesh.
1041 // TODO: not sure the temp native shape is freed when the mesh is rebuilt. When does this get freed?
1042 convexShape = baseMesh.physShapeInfo;
1043 }
1044 else
1045 {
1046 convexShape = physicsScene.PE.BuildConvexHullShapeFromMesh(physicsScene.World, baseMesh.physShapeInfo);
1047 convexShape.shapeKey = newMeshKey;
1048 ConvexHulls.Add(convexShape.shapeKey, retConvexHull);
1049 physicsScene.DetailLog("{0},BSShapeConvexHull.GetReference,addingNewlyCreatedShape,shape={1}",
1050 BSScene.DetailLogZero, convexShape);
1051 }
1052
1053 // Done with the base mesh
1054 baseMesh.Dereference(physicsScene);
1055
1056 retConvexHull.physShapeInfo = convexShape;
1057 }
1058 }
1059 return retConvexHull;
1060 }
1061 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
1062 {
1063 // Calling this reference means we want another handle to an existing shape
1064 // (usually linksets) so return this copy.
1065 IncrementReference();
1066 return this;
1067 }
1068 // Dereferencing a compound shape releases the hold on all the child shapes.
1069 public override void Dereference(BSScene physicsScene)
1070 {
1071 lock (ConvexHulls)
1072 {
1073 this.DecrementReference();
1074 physicsScene.DetailLog("{0},BSShapeConvexHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
1075 // TODO: schedule aging and destruction of unused meshes.
1076 }
1077 }
1078 // Loop through all the known hulls and return the description based on the physical address.
1079 public static bool TryGetConvexHullByPtr(BulletShape pShape, out BSShapeConvexHull outHull)
1080 {
1081 bool ret = false;
1082 BSShapeConvexHull foundDesc = null;
1083 lock (ConvexHulls)
1084 {
1085 foreach (BSShapeConvexHull sh in ConvexHulls.Values)
1086 {
1087 if (sh.physShapeInfo.ReferenceSame(pShape))
1088 {
1089 foundDesc = sh;
1090 ret = true;
1091 break;
1092 }
1093
1094 }
1095 }
1096 outHull = foundDesc;
1097 return ret;
1098 }
1099}
1100// ============================================================================================================
1101public class BSShapeGImpact : BSShape
1102{
1103 private static string LogHeader = "[BULLETSIM SHAPE GIMPACT]";
1104 public static Dictionary<System.UInt64, BSShapeGImpact> GImpacts = new Dictionary<System.UInt64, BSShapeGImpact>();
1105
1106 public BSShapeGImpact(BulletShape pShape) : base(pShape)
1107 {
1108 }
1109 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
1110 {
1111 float lod;
1112 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
1113
1114 physicsScene.DetailLog("{0},BSShapeGImpact,getReference,newKey={1},size={2},lod={3}",
1115 prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
1116
1117 BSShapeGImpact retGImpact = null;
1118 lock (GImpacts)
1119 {
1120 if (GImpacts.TryGetValue(newMeshKey, out retGImpact))
1121 {
1122 // The mesh has already been created. Return a new reference to same.
1123 retGImpact.IncrementReference();
1124 }
1125 else
1126 {
1127 retGImpact = new BSShapeGImpact(new BulletShape());
1128 BulletShape newShape = retGImpact.CreatePhysicalGImpact(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
1129
1130 // Check to see if mesh was created (might require an asset).
1131 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
1132 newShape.shapeKey = newMeshKey;
1133 if (!newShape.isNativeShape
1134 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedMeshing
1135 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedAssetFetch)
1136 {
1137 // If a mesh was what was created, remember the built shape for later sharing.
1138 // Also note that if meshing failed we put it in the mesh list as there is nothing
1139 // else to do about the mesh.
1140 GImpacts.Add(newMeshKey, retGImpact);
1141 }
1142
1143 retGImpact.physShapeInfo = newShape;
1144 }
1145 }
1146 return retGImpact;
1147 }
1148
1149 private BulletShape CreatePhysicalGImpact(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
1150 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
1151 {
1152 return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
1153 (w, iC, i, vC, v) => physicsScene.PE.CreateGImpactShape(w, iC, i, vC, v) );
1154 }
1155
1156 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
1157 {
1158 BSShape ret = null;
1159 // If the underlying shape is native, the actual shape has not been build (waiting for asset)
1160 // and we must create a copy of the native shape since they are never shared.
1161 if (physShapeInfo.HasPhysicalShape && physShapeInfo.isNativeShape)
1162 {
1163 // TODO: decide when the native shapes should be freed. Check in Dereference?
1164 ret = BSShapeNative.GetReference(pPhysicsScene, pPrim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
1165 }
1166 else
1167 {
1168 // Another reference to this shape is just counted.
1169 IncrementReference();
1170 ret = this;
1171 }
1172 return ret;
1173 }
1174 // Dereferencing a compound shape releases the hold on all the child shapes.
1175 public override void Dereference(BSScene physicsScene)
1176 {
1177 lock (GImpacts)
1178 {
1179 this.DecrementReference();
1180 physicsScene.DetailLog("{0},BSShapeGImpact.Dereference,shape={1}", BSScene.DetailLogZero, this);
1181 // TODO: schedule aging and destruction of unused meshes.
1182 }
1183 }
1184 // Loop through all the known hulls and return the description based on the physical address.
1185 public static bool TryGetGImpactByPtr(BulletShape pShape, out BSShapeGImpact outHull)
1186 {
1187 bool ret = false;
1188 BSShapeGImpact foundDesc = null;
1189 lock (GImpacts)
1190 {
1191 foreach (BSShapeGImpact sh in GImpacts.Values)
1192 {
1193 if (sh.physShapeInfo.ReferenceSame(pShape))
1194 {
1195 foundDesc = sh;
1196 ret = true;
1197 break;
1198 }
1199
1200 }
1201 }
1202 outHull = foundDesc;
1203 return ret;
215 } 1204 }
216 public override void Dereference(BSScene physicsScene) { }
217} 1205}
218 1206
1207// ============================================================================================================
219public class BSShapeAvatar : BSShape 1208public class BSShapeAvatar : BSShape
220{ 1209{
221 private static string LogHeader = "[BULLETSIM SHAPE AVATAR]"; 1210 private static string LogHeader = "[BULLETSIM SHAPE AVATAR]";
222 public BSShapeAvatar() : base() 1211 public BSShapeAvatar() : base()
223 { 1212 {
224 } 1213 }
225 public static BSShape GetReference(BSPhysObject prim) 1214 public static BSShape GetReference(BSPhysObject prim)
226 { 1215 {
1216 return new BSShapeNull();
1217 }
1218 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
1219 {
227 return new BSShapeNull(); 1220 return new BSShapeNull();
228 } 1221 }
229 public override void Dereference(BSScene physicsScene) { } 1222 public override void Dereference(BSScene physicsScene) { }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
index e4fecc3..8888d6d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -68,7 +68,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
68 68
69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z 69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z
70 // are the high and low points of the heightmap). 70 // are the high and low points of the heightmap).
71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, 71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
72 Vector3 minCoords, Vector3 maxCoords) 72 Vector3 minCoords, Vector3 maxCoords)
73 : base(physicsScene, regionBase, id) 73 : base(physicsScene, regionBase, id)
74 { 74 {
@@ -92,7 +92,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
92 private void BuildHeightmapTerrain() 92 private void BuildHeightmapTerrain()
93 { 93 {
94 // Create the terrain shape from the mapInfo 94 // Create the terrain shape from the mapInfo
95 m_mapInfo.terrainShape = PhysicsScene.PE.CreateTerrainShape( m_mapInfo.ID, 95 m_mapInfo.terrainShape = m_physicsScene.PE.CreateTerrainShape( m_mapInfo.ID,
96 new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ, 96 new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ,
97 m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin); 97 m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin);
98 98
@@ -103,26 +103,25 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
103 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); 103 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
104 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);
105 105
106 m_mapInfo.terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape, 106 m_mapInfo.terrainBody = m_physicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape,
107 m_mapInfo.ID, centerPos, Quaternion.Identity); 107 m_mapInfo.ID, centerPos, Quaternion.Identity);
108 108
109 // Set current terrain attributes 109 // Set current terrain attributes
110 PhysicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction); 110 m_physicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction);
111 PhysicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction); 111 m_physicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction);
112 PhysicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution); 112 m_physicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution);
113 PhysicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT); 113 m_physicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT);
114
115 m_mapInfo.terrainBody.collisionType = CollisionType.Terrain;
114 116
115 // Return the new terrain to the world of physical objects 117 // Return the new terrain to the world of physical objects
116 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_mapInfo.terrainBody); 118 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_mapInfo.terrainBody);
117 119
118 // redo its bounding box now that it is in the world 120 // redo its bounding box now that it is in the world
119 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_mapInfo.terrainBody); 121 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_mapInfo.terrainBody);
120
121 m_mapInfo.terrainBody.collisionType = CollisionType.Terrain;
122 m_mapInfo.terrainBody.ApplyCollisionMask(PhysicsScene);
123 122
124 // Make it so the terrain will not move or be considered for movement. 123 // Make it so the terrain will not move or be considered for movement.
125 PhysicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION); 124 m_physicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION);
126 125
127 return; 126 return;
128 } 127 }
@@ -134,9 +133,9 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
134 { 133 {
135 if (m_mapInfo.terrainBody.HasPhysicalBody) 134 if (m_mapInfo.terrainBody.HasPhysicalBody)
136 { 135 {
137 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_mapInfo.terrainBody); 136 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_mapInfo.terrainBody);
138 // Frees both the body and the shape. 137 // Frees both the body and the shape.
139 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_mapInfo.terrainBody); 138 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_mapInfo.terrainBody);
140 } 139 }
141 } 140 }
142 m_mapInfo = null; 141 m_mapInfo = null;
@@ -155,7 +154,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
155 catch 154 catch
156 { 155 {
157 // Sometimes they give us wonky values of X and Y. Give a warning and return something. 156 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
158 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", 157 m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
159 LogHeader, m_mapInfo.terrainRegionBase, pos); 158 LogHeader, m_mapInfo.terrainRegionBase, pos);
160 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; 159 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
161 } 160 }
@@ -165,7 +164,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
165 // The passed position is relative to the base of the region. 164 // The passed position is relative to the base of the region.
166 public override float GetWaterLevelAtXYZ(Vector3 pos) 165 public override float GetWaterLevelAtXYZ(Vector3 pos)
167 { 166 {
168 return PhysicsScene.SimpleWaterLevel; 167 return m_physicsScene.SimpleWaterLevel;
169 } 168 }
170} 169}
171} 170}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index cd15850..441d2d3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -50,14 +50,14 @@ public abstract class BSTerrainPhys : IDisposable
50 Mesh = 1 50 Mesh = 1
51 } 51 }
52 52
53 public BSScene PhysicsScene { get; private set; } 53 protected BSScene m_physicsScene { get; private set; }
54 // Base of the region in world coordinates. Coordinates inside the region are relative to this. 54 // Base of the region in world coordinates. Coordinates inside the region are relative to this.
55 public Vector3 TerrainBase { get; private set; } 55 public Vector3 TerrainBase { get; private set; }
56 public uint ID { get; private set; } 56 public uint ID { get; private set; }
57 57
58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) 58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id)
59 { 59 {
60 PhysicsScene = physicsScene; 60 m_physicsScene = physicsScene;
61 TerrainBase = regionBase; 61 TerrainBase = regionBase;
62 ID = id; 62 ID = id;
63 } 63 }
@@ -86,7 +86,7 @@ public sealed class BSTerrainManager : IDisposable
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
88 // The scene that I am part of 88 // The scene that I am part of
89 private BSScene PhysicsScene { get; set; } 89 private BSScene m_physicsScene { get; set; }
90 90
91 // The ground plane created to keep thing from falling to infinity. 91 // The ground plane created to keep thing from falling to infinity.
92 private BulletBody m_groundPlane; 92 private BulletBody m_groundPlane;
@@ -113,7 +113,7 @@ public sealed class BSTerrainManager : IDisposable
113 113
114 public BSTerrainManager(BSScene physicsScene) 114 public BSTerrainManager(BSScene physicsScene)
115 { 115 {
116 PhysicsScene = physicsScene; 116 m_physicsScene = physicsScene;
117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>(); 117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
118 118
119 // Assume one region of default size 119 // Assume one region of default size
@@ -132,21 +132,22 @@ public sealed class BSTerrainManager : IDisposable
132 // 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.
133 public void CreateInitialGroundPlaneAndTerrain() 133 public void CreateInitialGroundPlaneAndTerrain()
134 { 134 {
135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName); 135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName);
136 // The ground plane is here to catch things that are trying to drop to negative infinity 136 // The ground plane is here to catch things that are trying to drop to negative infinity
137 BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin); 137 BulletShape groundPlaneShape = m_physicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
138 m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape, 138 m_groundPlane = m_physicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
139 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity); 139 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity);
140 140
141 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane);
142 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane);
143 // Ground plane does not move
144 PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
145 // Everything collides with the ground plane. 141 // Everything collides with the ground plane.
146 m_groundPlane.collisionType = CollisionType.Groundplane; 142 m_groundPlane.collisionType = CollisionType.Groundplane;
147 m_groundPlane.ApplyCollisionMask(PhysicsScene);
148 143
149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); 144 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_groundPlane);
145 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_groundPlane);
146
147 // Ground plane does not move
148 m_physicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
149
150 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(m_physicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
150 lock (m_terrains) 151 lock (m_terrains)
151 { 152 {
152 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. 153 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
@@ -157,12 +158,12 @@ public sealed class BSTerrainManager : IDisposable
157 // Release all the terrain structures we might have allocated 158 // Release all the terrain structures we might have allocated
158 public void ReleaseGroundPlaneAndTerrain() 159 public void ReleaseGroundPlaneAndTerrain()
159 { 160 {
160 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName); 161 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName);
161 if (m_groundPlane.HasPhysicalBody) 162 if (m_groundPlane.HasPhysicalBody)
162 { 163 {
163 if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane)) 164 if (m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_groundPlane))
164 { 165 {
165 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_groundPlane); 166 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_groundPlane);
166 } 167 }
167 m_groundPlane.Clear(); 168 m_groundPlane.Clear();
168 } 169 }
@@ -188,7 +189,7 @@ public sealed class BSTerrainManager : IDisposable
188 float[] localHeightMap = heightMap; 189 float[] localHeightMap = heightMap;
189 // If there are multiple requests for changes to the same terrain between ticks, 190 // If there are multiple requests for changes to the same terrain between ticks,
190 // only do that last one. 191 // only do that last one.
191 PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate() 192 m_physicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate()
192 { 193 {
193 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) 194 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
194 { 195 {
@@ -213,13 +214,13 @@ public sealed class BSTerrainManager : IDisposable
213 }); 214 });
214 } 215 }
215 216
216 // Another region is calling this region passing a terrain. 217 // Another region is calling this region and passing a terrain.
217 // A region that is not the mega-region root will pass its terrain to the root region so the root region 218 // A region that is not the mega-region root will pass its terrain to the root region so the root region
218 // physics engine will have all the terrains. 219 // physics engine will have all the terrains.
219 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) 220 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
220 { 221 {
221 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread. 222 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread.
222 PhysicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + m_worldOffset.ToString(), 0, delegate() 223 m_physicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate()
223 { 224 {
224 UpdateTerrain(id, heightMap, minCoords, maxCoords); 225 UpdateTerrain(id, heightMap, minCoords, maxCoords);
225 }); 226 });
@@ -306,7 +307,7 @@ public sealed class BSTerrainManager : IDisposable
306 newTerrainID = ++m_terrainCount; 307 newTerrainID = ++m_terrainCount;
307 308
308 DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}", 309 DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
309 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); 310 BSScene.DetailLogZero, newTerrainID, minCoords, maxCoords);
310 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); 311 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
311 m_terrains.Add(terrainRegionBase, newTerrainPhys); 312 m_terrains.Add(terrainRegionBase, newTerrainPhys);
312 313
@@ -318,26 +319,26 @@ public sealed class BSTerrainManager : IDisposable
318 // TODO: redo terrain implementation selection to allow other base types than heightMap. 319 // TODO: redo terrain implementation selection to allow other base types than heightMap.
319 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) 320 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
320 { 321 {
321 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", 322 m_physicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
322 LogHeader, PhysicsScene.RegionName, terrainRegionBase, 323 LogHeader, m_physicsScene.RegionName, terrainRegionBase,
323 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation); 324 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation);
324 BSTerrainPhys newTerrainPhys = null; 325 BSTerrainPhys newTerrainPhys = null;
325 switch ((int)BSParam.TerrainImplementation) 326 switch ((int)BSParam.TerrainImplementation)
326 { 327 {
327 case (int)BSTerrainPhys.TerrainImplementation.Heightmap: 328 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
328 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, 329 newTerrainPhys = new BSTerrainHeightmap(m_physicsScene, terrainRegionBase, id,
329 heightMap, minCoords, maxCoords); 330 heightMap, minCoords, maxCoords);
330 break; 331 break;
331 case (int)BSTerrainPhys.TerrainImplementation.Mesh: 332 case (int)BSTerrainPhys.TerrainImplementation.Mesh:
332 newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, 333 newTerrainPhys = new BSTerrainMesh(m_physicsScene, terrainRegionBase, id,
333 heightMap, minCoords, maxCoords); 334 heightMap, minCoords, maxCoords);
334 break; 335 break;
335 default: 336 default:
336 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", 337 m_physicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
337 LogHeader, 338 LogHeader,
338 (int)BSParam.TerrainImplementation, 339 (int)BSParam.TerrainImplementation,
339 BSParam.TerrainImplementation, 340 BSParam.TerrainImplementation,
340 PhysicsScene.RegionName, terrainRegionBase); 341 m_physicsScene.RegionName, terrainRegionBase);
341 break; 342 break;
342 } 343 }
343 return newTerrainPhys; 344 return newTerrainPhys;
@@ -354,6 +355,8 @@ public sealed class BSTerrainManager : IDisposable
354 // Return a new position that is over known terrain if the position is outside our terrain. 355 // Return a new position that is over known terrain if the position is outside our terrain.
355 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos) 356 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos)
356 { 357 {
358 float edgeEpsilon = 0.1f;
359
357 Vector3 ret = pPos; 360 Vector3 ret = pPos;
358 361
359 // First, base addresses are never negative so correct for that possible problem. 362 // First, base addresses are never negative so correct for that possible problem.
@@ -378,10 +381,19 @@ public sealed class BSTerrainManager : IDisposable
378 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region. 381 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region.
379 382
380 // Must be off the top of a region. Find an adjacent region to move into. 383 // Must be off the top of a region. Find an adjacent region to move into.
384 // The returned terrain is always 'lower'. That is, closer to <0,0>.
381 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ); 385 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ);
382 386
383 ret.X = Math.Min(ret.X, adjacentTerrainBase.X + (ret.X % DefaultRegionSize.X)); 387 if (adjacentTerrainBase.X < terrainBaseXYZ.X)
384 ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + (ret.X % DefaultRegionSize.Y)); 388 {
389 // moving down into a new region in the X dimension. New position will be the max in the new base.
390 ret.X = adjacentTerrainBase.X + DefaultRegionSize.X - edgeEpsilon;
391 }
392 if (adjacentTerrainBase.Y < terrainBaseXYZ.Y)
393 {
394 // moving down into a new region in the X dimension. New position will be the max in the new base.
395 ret.Y = adjacentTerrainBase.Y + DefaultRegionSize.Y - edgeEpsilon;
396 }
385 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}", 397 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
386 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret); 398 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
387 399
@@ -429,8 +441,8 @@ public sealed class BSTerrainManager : IDisposable
429 } 441 }
430 else 442 else
431 { 443 {
432 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", 444 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
433 LogHeader, PhysicsScene.RegionName, tX, tY); 445 LogHeader, m_physicsScene.RegionName, tX, tY);
434 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", 446 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}",
435 BSScene.DetailLogZero, pos, terrainBaseXYZ); 447 BSScene.DetailLogZero, pos, terrainBaseXYZ);
436 } 448 }
@@ -451,8 +463,8 @@ public sealed class BSTerrainManager : IDisposable
451 } 463 }
452 else 464 else
453 { 465 {
454 PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}", 466 m_physicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}",
455 LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret); 467 LogHeader, m_physicsScene.RegionName, pos, terrainBaseXYZ, ret);
456 } 468 }
457 return ret; 469 return ret;
458 } 470 }
@@ -564,7 +576,7 @@ public sealed class BSTerrainManager : IDisposable
564 576
565 private void DetailLog(string msg, params Object[] args) 577 private void DetailLog(string msg, params Object[] args)
566 { 578 {
567 PhysicsScene.PhysicsLogging.Write(msg, args); 579 m_physicsScene.PhysicsLogging.Write(msg, args);
568 } 580 }
569} 581}
570} 582}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
index 2ce1513..e4ca098 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -51,7 +51,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
51 BulletShape m_terrainShape; 51 BulletShape m_terrainShape;
52 BulletBody m_terrainBody; 52 BulletBody m_terrainBody;
53 53
54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) 54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
55 : base(physicsScene, regionBase, id) 55 : base(physicsScene, regionBase, id)
56 { 56 {
57 } 57 }
@@ -62,7 +62,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
62 } 62 }
63 63
64 // Create terrain mesh from a heightmap. 64 // Create terrain mesh from a heightmap.
65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, 65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
66 Vector3 minCoords, Vector3 maxCoords) 66 Vector3 minCoords, Vector3 maxCoords)
67 : base(physicsScene, regionBase, id) 67 : base(physicsScene, regionBase, id)
68 { 68 {
@@ -80,7 +80,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
80 if (BSParam.TerrainMeshMagnification == 1) 80 if (BSParam.TerrainMeshMagnification == 1)
81 { 81 {
82 // If a magnification of one, use the old routine that is tried and true. 82 // If a magnification of one, use the old routine that is tried and true.
83 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, 83 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(m_physicsScene,
84 initialMap, m_sizeX, m_sizeY, // input size 84 initialMap, m_sizeX, m_sizeY, // input size
85 Vector3.Zero, // base for mesh 85 Vector3.Zero, // base for mesh
86 out indicesCount, out indices, out verticesCount, out vertices); 86 out indicesCount, out indices, out verticesCount, out vertices);
@@ -88,7 +88,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
88 else 88 else
89 { 89 {
90 // Other magnifications use the newer routine 90 // Other magnifications use the newer routine
91 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(PhysicsScene, 91 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(m_physicsScene,
92 initialMap, m_sizeX, m_sizeY, // input size 92 initialMap, m_sizeX, m_sizeY, // input size
93 BSParam.TerrainMeshMagnification, 93 BSParam.TerrainMeshMagnification,
94 physicsScene.TerrainManager.DefaultRegionSize, 94 physicsScene.TerrainManager.DefaultRegionSize,
@@ -98,21 +98,21 @@ public sealed class BSTerrainMesh : BSTerrainPhys
98 if (!meshCreationSuccess) 98 if (!meshCreationSuccess)
99 { 99 {
100 // DISASTER!! 100 // DISASTER!!
101 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID); 101 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID);
102 PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); 102 m_physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
103 // Something is very messed up and a crash is in our future. 103 // Something is very messed up and a crash is in our future.
104 return; 104 return;
105 } 105 }
106 106
107 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}", 107 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}",
108 BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length); 108 BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length);
109 109
110 m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices); 110 m_terrainShape = m_physicsScene.PE.CreateMeshShape(m_physicsScene.World, indicesCount, indices, verticesCount, vertices);
111 if (!m_terrainShape.HasPhysicalShape) 111 if (!m_terrainShape.HasPhysicalShape)
112 { 112 {
113 // DISASTER!! 113 // DISASTER!!
114 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID); 114 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID);
115 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); 115 m_physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
116 // Something is very messed up and a crash is in our future. 116 // Something is very messed up and a crash is in our future.
117 return; 117 return;
118 } 118 }
@@ -120,52 +120,52 @@ public sealed class BSTerrainMesh : BSTerrainPhys
120 Vector3 pos = regionBase; 120 Vector3 pos = regionBase;
121 Quaternion rot = Quaternion.Identity; 121 Quaternion rot = Quaternion.Identity;
122 122
123 m_terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot); 123 m_terrainBody = m_physicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot);
124 if (!m_terrainBody.HasPhysicalBody) 124 if (!m_terrainBody.HasPhysicalBody)
125 { 125 {
126 // DISASTER!! 126 // DISASTER!!
127 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); 127 m_physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
128 // Something is very messed up and a crash is in our future. 128 // Something is very messed up and a crash is in our future.
129 return; 129 return;
130 } 130 }
131 physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin); 131 physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin);
132 132
133 // Set current terrain attributes 133 // Set current terrain attributes
134 PhysicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction); 134 m_physicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
135 PhysicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction); 135 m_physicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
136 PhysicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution); 136 m_physicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
137 PhysicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold); 137 m_physicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold);
138 PhysicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT); 138 m_physicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);
139 139
140 // Static objects are not very massive. 140 // Static objects are not very massive.
141 PhysicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero); 141 m_physicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero);
142 142
143 // Put the new terrain to the world of physical objects 143 // Put the new terrain to the world of physical objects
144 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_terrainBody); 144 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_terrainBody);
145 145
146 // Redo its bounding box now that it is in the world 146 // Redo its bounding box now that it is in the world
147 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_terrainBody); 147 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_terrainBody);
148 148
149 m_terrainBody.collisionType = CollisionType.Terrain; 149 m_terrainBody.collisionType = CollisionType.Terrain;
150 m_terrainBody.ApplyCollisionMask(PhysicsScene); 150 m_terrainBody.ApplyCollisionMask(m_physicsScene);
151 151
152 if (BSParam.UseSingleSidedMeshes) 152 if (BSParam.UseSingleSidedMeshes)
153 { 153 {
154 PhysicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id); 154 m_physicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id);
155 PhysicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK); 155 m_physicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
156 } 156 }
157 157
158 // Make it so the terrain will not move or be considered for movement. 158 // Make it so the terrain will not move or be considered for movement.
159 PhysicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION); 159 m_physicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION);
160 } 160 }
161 161
162 public override void Dispose() 162 public override void Dispose()
163 { 163 {
164 if (m_terrainBody.HasPhysicalBody) 164 if (m_terrainBody.HasPhysicalBody)
165 { 165 {
166 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_terrainBody); 166 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_terrainBody);
167 // Frees both the body and the shape. 167 // Frees both the body and the shape.
168 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_terrainBody); 168 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_terrainBody);
169 m_terrainBody.Clear(); 169 m_terrainBody.Clear();
170 m_terrainShape.Clear(); 170 m_terrainShape.Clear();
171 } 171 }
@@ -185,7 +185,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
185 catch 185 catch
186 { 186 {
187 // Sometimes they give us wonky values of X and Y. Give a warning and return something. 187 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
188 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", 188 m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
189 LogHeader, TerrainBase, pos); 189 LogHeader, TerrainBase, pos);
190 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; 190 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
191 } 191 }
@@ -195,7 +195,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
195 // The passed position is relative to the base of the region. 195 // The passed position is relative to the base of the region.
196 public override float GetWaterLevelAtXYZ(Vector3 pos) 196 public override float GetWaterLevelAtXYZ(Vector3 pos)
197 { 197 {
198 return PhysicsScene.SimpleWaterLevel; 198 return m_physicsScene.SimpleWaterLevel;
199 } 199 }
200 200
201 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). 201 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
index 8012d91..971ff9f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
@@ -104,11 +104,11 @@ public class BulletShape
104{ 104{
105 public BulletShape() 105 public BulletShape()
106 { 106 {
107 type = BSPhysicsShapeType.SHAPE_UNKNOWN; 107 shapeType = BSPhysicsShapeType.SHAPE_UNKNOWN;
108 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; 108 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
109 isNativeShape = false; 109 isNativeShape = false;
110 } 110 }
111 public BSPhysicsShapeType type; 111 public BSPhysicsShapeType shapeType;
112 public System.UInt64 shapeKey; 112 public System.UInt64 shapeKey;
113 public bool isNativeShape; 113 public bool isNativeShape;
114 114
@@ -133,7 +133,7 @@ public class BulletShape
133 buff.Append("<p="); 133 buff.Append("<p=");
134 buff.Append(AddrString); 134 buff.Append(AddrString);
135 buff.Append(",s="); 135 buff.Append(",s=");
136 buff.Append(type.ToString()); 136 buff.Append(shapeType.ToString());
137 buff.Append(",k="); 137 buff.Append(",k=");
138 buff.Append(shapeKey.ToString("X")); 138 buff.Append(shapeKey.ToString("X"));
139 buff.Append(",n="); 139 buff.Append(",n=");
@@ -224,42 +224,43 @@ public static class BulletSimData
224// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code 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 225// but, instead, use references to this dictionary. Finding and debugging
226// collision flag problems will be made easier. 226// collision flag problems will be made easier.
227public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks 227public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks
228 = new Dictionary<CollisionType, CollisionTypeFilterGroup>() 228 = new Dictionary<CollisionType, CollisionTypeFilterGroup>()
229{ 229{
230 { CollisionType.Avatar, 230 { CollisionType.Avatar,
231 new CollisionTypeFilterGroup(CollisionType.Avatar, 231 new CollisionTypeFilterGroup(CollisionType.Avatar,
232 (uint)CollisionFilterGroups.BCharacterGroup, 232 (uint)CollisionFilterGroups.BCharacterGroup,
233 (uint)CollisionFilterGroups.BAllGroup) 233 (uint)CollisionFilterGroups.BAllGroup)
234 }, 234 },
235 { CollisionType.Groundplane, 235 { CollisionType.Groundplane,
236 new CollisionTypeFilterGroup(CollisionType.Groundplane, 236 new CollisionTypeFilterGroup(CollisionType.Groundplane,
237 (uint)CollisionFilterGroups.BGroundPlaneGroup, 237 (uint)CollisionFilterGroups.BGroundPlaneGroup,
238 (uint)CollisionFilterGroups.BAllGroup) 238 // (uint)CollisionFilterGroups.BAllGroup)
239 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
239 }, 240 },
240 { CollisionType.Terrain, 241 { CollisionType.Terrain,
241 new CollisionTypeFilterGroup(CollisionType.Terrain, 242 new CollisionTypeFilterGroup(CollisionType.Terrain,
242 (uint)CollisionFilterGroups.BTerrainGroup, 243 (uint)CollisionFilterGroups.BTerrainGroup,
243 (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup)) 244 (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup))
244 }, 245 },
245 { CollisionType.Static, 246 { CollisionType.Static,
246 new CollisionTypeFilterGroup(CollisionType.Static, 247 new CollisionTypeFilterGroup(CollisionType.Static,
247 (uint)CollisionFilterGroups.BStaticGroup, 248 (uint)CollisionFilterGroups.BStaticGroup,
248 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) 249 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
249 }, 250 },
250 { CollisionType.Dynamic, 251 { CollisionType.Dynamic,
251 new CollisionTypeFilterGroup(CollisionType.Dynamic, 252 new CollisionTypeFilterGroup(CollisionType.Dynamic,
252 (uint)CollisionFilterGroups.BSolidGroup, 253 (uint)CollisionFilterGroups.BSolidGroup,
253 (uint)(CollisionFilterGroups.BAllGroup)) 254 (uint)(CollisionFilterGroups.BAllGroup))
254 }, 255 },
255 { CollisionType.VolumeDetect, 256 { CollisionType.VolumeDetect,
256 new CollisionTypeFilterGroup(CollisionType.VolumeDetect, 257 new CollisionTypeFilterGroup(CollisionType.VolumeDetect,
257 (uint)CollisionFilterGroups.BSensorTrigger, 258 (uint)CollisionFilterGroups.BSensorTrigger,
258 (uint)(~CollisionFilterGroups.BSensorTrigger)) 259 (uint)(~CollisionFilterGroups.BSensorTrigger))
259 }, 260 },
260 { CollisionType.LinksetChild, 261 { CollisionType.LinksetChild,
261 new CollisionTypeFilterGroup(CollisionType.LinksetChild, 262 new CollisionTypeFilterGroup(CollisionType.LinksetChild,
262 (uint)CollisionFilterGroups.BLinksetChildGroup, 263 (uint)CollisionFilterGroups.BLinksetChildGroup,
263 (uint)(CollisionFilterGroups.BNoneGroup)) 264 (uint)(CollisionFilterGroups.BNoneGroup))
264 // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) 265 // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
265 }, 266 },
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 8a15abe..0453376 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -1,65 +1,61 @@
1CURRENT PRIORITIES 1CURRENT PROBLEMS TO FIX AND/OR LOOK AT
2================================================= 2=================================================
3Use the HACD convex hull routine in Bullet rather than the C# version. 3Vehicle buoyancy. Computed correctly? Possibly creating very large effective mass.
4 Speed up hullifying large meshes. 4 Interaction of llSetBuoyancy and vehicle buoyancy. Should be additive?
5 Negative buoyancy computed correctly
6Center-of-gravity
7Computation of mesh mass. How done? How should it be done?
5Enable vehicle border crossings (at least as poorly as ODE) 8Enable vehicle border crossings (at least as poorly as ODE)
6 Terrain skirts 9 Terrain skirts
7 Avatar created in previous region and not new region when crossing border 10 Avatar created in previous region and not new region when crossing border
8 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE) 11 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
9Lock axis 12User settable terrain mesh
13 Allow specifying as convex or concave and use different getHeight functions depending
14Boats, when turning nose down into the water
15 Acts like rotation around Z is also effecting rotation around X and Y
10Deleting a linkset while standing on the root will leave the physical shape of the root behind. 16Deleting a linkset while standing on the root will leave the physical shape of the root behind.
11 Not sure if it is because standing on it. Done with large prim linksets. 17 Not sure if it is because standing on it. Done with large prim linksets.
12Linkset child rotations. 18Linkset child rotations.
13 Nebadon spiral tube has middle sections which are rotated wrong. 19 Nebadon spiral tube has middle sections which are rotated wrong.
14 Select linked spiral tube. Delink and note where the middle section ends up. 20 Select linked spiral tube. Delink and note where the middle section ends up.
15Vehicle angular vertical attraction
16vehicle angular banking
17Center-of-gravity
18Vehicle angular deflection
19 Preferred orientation angular correction fix
20when should angular and linear motor targets be zeroed? when selected?
21 Need a vehicle.clear()? Or an 'else' in prestep if not physical.
22Teravus llMoveToTarget script debug 21Teravus llMoveToTarget script debug
23 Mixing of hover, buoyancy/gravity, moveToTarget, into one force 22 Mixing of hover, buoyancy/gravity, moveToTarget, into one force
24 Setting hover height to zero disables hover even if hover flags are on (from SL wiki) 23 Setting hover height to zero disables hover even if hover flags are on (from SL wiki)
25limitMotorUp calibration (more down?) 24limitMotorUp calibration (more down?)
26llRotLookAt 25llRotLookAt
27llLookAt 26llLookAt
28Avatars walking up stairs (HALF DONE) 27Convert to avatar mesh capsule. Include rotation of capsule.
29Avatar movement
30 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
31 walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
32 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
33Vehicle script tuning/debugging 28Vehicle script tuning/debugging
34 Avanti speed script 29 Avanti speed script
35 Weapon shooter script 30 Weapon shooter script
36Move material definitions (friction, ...) into simulator. 31Move material definitions (friction, ...) into simulator.
37Add material densities to the material types. 32osGetPhysicsEngineVerion() and create a version code for the C++ DLL
38Terrain detail: double terrain mesh detail
39One sided meshes? Should terrain be built into a closed shape? 33One sided meshes? Should terrain be built into a closed shape?
40 When meshes get partially wedged into the terrain, they cannot push themselves out. 34 When meshes get partially wedged into the terrain, they cannot push themselves out.
41 It is possible that Bullet processes collisions whether entering or leaving a mesh. 35 It is possible that Bullet processes collisions whether entering or leaving a mesh.
42 Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869 36 Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869
37Small physical objects do not interact correctly
38 Create chain of .5x.5x.1 torui and make all but top physical so to hang.
39 The chain will fall apart and pairs will dance around on ground
40 Chains of 1x1x.2 will stay connected but will dance.
41 Chains above 2x2x.4 are more stable and get stablier as torui get larger.
43 42
44VEHICLES TODO LIST: 43VEHICLES TODO LIST:
45================================================= 44=================================================
46Border crossing with linked vehicle causes crash 45LINEAR_MOTOR_DIRECTION values should be clamped to reasonable numbers.
47 20121129.1411: editting/moving phys object across region boundries causes crash 46 What are the limits in SL?
48 getPos-> btRigidBody::upcast -> getBodyType -> BOOM 47 Same for other velocity settings.
49Vehicles (Move smoothly) 48UBit improvements to remove rubber-banding of avatars sitting on vehicle child prims:
49 https://github.com/UbitUmarov/Ubit-opensim
50Some vehicles should not be able to turn if no speed or off ground. 50Some vehicles should not be able to turn if no speed or off ground.
51What to do if vehicle and prim buoyancy differ?
52Cannot edit/move a vehicle being ridden: it jumps back to the origional position. 51Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
53Neb car jiggling left and right 52Neb car jiggling left and right
54 Happens on terrain and any other mesh object. Flat cubes are much smoother. 53 Happens on terrain and any other mesh object. Flat cubes are much smoother.
55 This has been reduced but not eliminated. 54 This has been reduced but not eliminated.
56Implement referenceFrame for all the motion routines. 55Implement referenceFrame for all the motion routines.
57For limitMotorUp, use raycast down to find if vehicle is in the air.
58Verify llGetVel() is returning a smooth and good value for vehicle movement. 56Verify llGetVel() is returning a smooth and good value for vehicle movement.
59llGetVel() should return the root's velocity if requested in a child prim. 57llGetVel() should return the root's velocity if requested in a child prim.
60Implement function efficiency for lineaar and angular motion. 58Implement function efficiency for lineaar and angular motion.
61After getting off a vehicle, the root prim is phantom (can be walked through)
62 Need to force a position update for the root prim after compound shape destruction
63Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint) 59Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
64Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties(). 60Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties().
65 A kludge that isn't fixing the real problem of Bullet adding extra motion. 61 A kludge that isn't fixing the real problem of Bullet adding extra motion.
@@ -68,11 +64,10 @@ Incorporate inter-relationship of angular corrections. For instance, angularDefl
68 creates over-correction and over-shoot and wabbling. 64 creates over-correction and over-shoot and wabbling.
69Vehicle attributes are not restored when a vehicle is rezzed on region creation 65Vehicle attributes are not restored when a vehicle is rezzed on region creation
70 Create vehicle, setup vehicle properties, restart region, vehicle is not reinitialized. 66 Create vehicle, setup vehicle properties, restart region, vehicle is not reinitialized.
67What to do if vehicle and prim buoyancy differ?
71 68
72GENERAL TODO LIST: 69GENERAL TODO LIST:
73================================================= 70=================================================
74Explore btGImpactMeshShape as alternative to convex hulls for simplified physical objects.
75 Regular triangle meshes don't do physical collisions.
76Resitution of a prim works on another prim but not on terrain. 71Resitution of a prim works on another prim but not on terrain.
77 The dropped prim doesn't bounce properly on the terrain. 72 The dropped prim doesn't bounce properly on the terrain.
78Add a sanity check for PIDTarget location. 73Add a sanity check for PIDTarget location.
@@ -98,29 +93,15 @@ Revisit CollisionMargin. Builders notice the 0.04 spacing between prims.
98Duplicating a physical prim causes old prim to jump away 93Duplicating a physical prim causes old prim to jump away
99 Dup a phys prim and the original become unselected and thus interacts w/ selected prim. 94 Dup a phys prim and the original become unselected and thus interacts w/ selected prim.
100Scenes with hundred of thousands of static objects take a lot of physics CPU time. 95Scenes with hundred of thousands of static objects take a lot of physics CPU time.
101BSPrim.Force should set a continious force on the prim. The force should be
102 applied each tick. Some limits?
103Gun sending shooter flying. 96Gun sending shooter flying.
104Collision margin (gap between physical objects lying on each other) 97Collision margin (gap between physical objects lying on each other)
105Boundry checking (crashes related to crossing boundry) 98Boundry checking (crashes related to crossing boundry)
106 Add check for border edge position for avatars and objects. 99 Add check for border edge position for avatars and objects.
107 Verify the events are created for border crossings. 100 Verify the events are created for border crossings.
108Avatar rotation (check out changes to ScenePresence for physical rotation)
109Avatar running (what does phys engine need to do?)
110Small physical objects do not interact correctly
111 Create chain of .5x.5x.1 torui and make all but top physical so to hang.
112 The chain will fall apart and pairs will dance around on ground
113 Chains of 1x1x.2 will stay connected but will dance.
114 Chains above 2x2x.4 are more stable and get stablier as torui get larger.
115Add PID motor for avatar movement (slow to stop, ...)
116setForce should set a constant force. Different than AddImpulse.
117Implement raycast.
118Implement ShapeCollection.Dispose() 101Implement ShapeCollection.Dispose()
119Implement water as a plain so raycasting and collisions can happen with same. 102Implement water as a plain or mesh so raycasting and collisions can happen with same.
120Add collision penetration return 103Add collision penetration return
121 Add field passed back by BulletSim.dll and fill with info in ManifoldConstact.GetDistance() 104 Add field passed back by BulletSim.dll and fill with info in ManifoldConstact.GetDistance()
122Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
123 Also osGetPhysicsEngineVerion() maybe.
124Linkset.Position and Linkset.Orientation requre rewrite to properly return 105Linkset.Position and Linkset.Orientation requre rewrite to properly return
125 child position. LinksetConstraint acts like it's at taint time!! 106 child position. LinksetConstraint acts like it's at taint time!!
126Implement LockAngularMotion -- implements llSetStatus(ROTATE_AXIS_*, T/F) 107Implement LockAngularMotion -- implements llSetStatus(ROTATE_AXIS_*, T/F)
@@ -132,9 +113,6 @@ Selecting and deselecting physical objects causes CPU processing time to jump
132Re-implement buoyancy as a separate force on the object rather than diddling gravity. 113Re-implement buoyancy as a separate force on the object rather than diddling gravity.
133 Register a pre-step event to add the force. 114 Register a pre-step event to add the force.
134More efficient memory usage when passing hull information from BSPrim to BulletSim 115More efficient memory usage when passing hull information from BSPrim to BulletSim
135Avatar movement motor check for zero or small movement. Somehow suppress small movements
136 when avatar has stopped and is just standing. Simple test for near zero has
137 the problem of preventing starting up (increase from zero) especially when falling.
138Physical and phantom will drop through the terrain 116Physical and phantom will drop through the terrain
139 117
140 118
@@ -168,6 +146,7 @@ Eliminate collisions between objects in a linkset. (LinksetConstraint)
168 146
169MORE 147MORE
170====================================================== 148======================================================
149Compute avatar size and scale correctly. Now it is a bit off from the capsule size.
171Create tests for different interface components 150Create tests for different interface components
172 Have test objects/scripts measure themselves and turn color if correct/bad 151 Have test objects/scripts measure themselves and turn color if correct/bad
173 Test functions in SL and calibrate correctness there 152 Test functions in SL and calibrate correctness there
@@ -176,7 +155,6 @@ Do we need to do convex hulls all the time? Can complex meshes be left meshes?
176 There is some problem with meshes and collisions 155 There is some problem with meshes and collisions
177 Hulls are not as detailed as meshes. Hulled vehicles insides are different shape. 156 Hulls are not as detailed as meshes. Hulled vehicles insides are different shape.
178Debounce avatar contact so legs don't keep folding up when standing. 157Debounce avatar contact so legs don't keep folding up when standing.
179Implement LSL physics controls. Like STATUS_ROTATE_X.
180Add border extensions to terrain to help region crossings and objects leaving region. 158Add border extensions to terrain to help region crossings and objects leaving region.
181Use a different capsule shape for avatar when sitting 159Use a different capsule shape for avatar when sitting
182 LL uses a pyrimidal shape scaled by the avatar's bounding box 160 LL uses a pyrimidal shape scaled by the avatar's bounding box
@@ -209,8 +187,6 @@ Keep avatar scaling correct. http://pennycow.blogspot.fr/2011/07/matter-of-scale
209 187
210INTERNAL IMPROVEMENT/CLEANUP 188INTERNAL IMPROVEMENT/CLEANUP
211================================================= 189=================================================
212Can the 'inTaintTime' flag be cleaned up and used? For instance, a call to
213 BSScene.TaintedObject() could immediately execute the callback if already in taint time.
214Create the physical wrapper classes (BulletBody, BulletShape) by methods on 190Create the physical wrapper classes (BulletBody, BulletShape) by methods on
215 BSAPITemplate and make their actual implementation Bullet engine specific. 191 BSAPITemplate and make their actual implementation Bullet engine specific.
216 For the short term, just call the existing functions in ShapeCollection. 192 For the short term, just call the existing functions in ShapeCollection.
@@ -344,3 +320,60 @@ Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
344 Verify that angular motion specified around Z moves in the vehicle coordinates. 320 Verify that angular motion specified around Z moves in the vehicle coordinates.
345 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates. 321 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates.
346Nebadon vehicles turning funny in arena (DONE) 322Nebadon vehicles turning funny in arena (DONE)
323Lock axis (DONE 20130401)
324Terrain detail: double terrain mesh detail (DONE)
325Use the HACD convex hull routine in Bullet rather than the C# version.
326 Speed up hullifying large meshes. (DONE)
327Vehicle ride, get up, ride again. Second time vehicle does not act correctly.
328 Have to rez new vehicle and delete the old to fix situation.
329 (DONE 20130520: normalize rotations)
330Hitting RESET on Nebadon's vehicle while riding causes vehicle to get into odd
331 position state where it will not settle onto ground properly, etc
332 (DONE 20130520: normalize rotations)
333Two of Nebadon vehicles in a sim max the CPU. This is new.
334 (DONE 20130520: two problems: if asset failed to mesh, constantly refetched
335 asset; vehicle was sending too many messages to all linkset members)
336Add material densities to the material types. (WILL NOT BE DONE: not how it is done)
337Avatars walking up stairs (DONE)
338Avatar movement
339 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
340 walking up stairs is not calibrated correctly (stairs out of Kepler cabin) (DONE)
341 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
342After getting off a vehicle, the root prim is phantom (can be walked through)
343 Need to force a position update for the root prim after compound shape destruction
344 (DONE)
345Explore btGImpactMeshShape as alternative to convex hulls for simplified physical objects.
346 Regular triangle meshes don't do physical collisions.
347 (DONE: discovered GImpact is VERY CPU intensive)
348Script changing rotation of child prim while vehicle moving (eg turning wheel) causes
349 the wheel to appear to jump back. Looks like sending position from previous update.
350 (DONE: redo of compound linksets fixed problem)
351Refarb compound linkset creation to create a pseudo-root for center-of-mass
352 Let children change their shape to physical indendently and just add shapes to compound
353 (DONE: redo of compound linkset fixed problem)
354Vehicle angular vertical attraction (DONE: vegaslon code)
355vehicle angular banking (DONE: vegaslon code)
356Vehicle angular deflection (DONE: vegaslon code)
357 Preferred orientation angular correction fix
358Vehicles (Move smoothly)
359For limitMotorUp, use raycast down to find if vehicle is in the air.
360 (WILL NOT BE DONE: gravity does the job well enough)
361BSPrim.Force should set a continious force on the prim. The force should be
362 applied each tick. Some limits?
363 (DONE: added physical actors. Implemented SetForce, SetTorque, ...)
364Implement LSL physics controls. Like STATUS_ROTATE_X. (DONE)
365Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
366Avatar rotation (check out changes to ScenePresence for physical rotation) (DONE)
367Avatar running (what does phys engine need to do?) (DONE: multiplies run factor by walking force)
368setForce should set a constant force. Different than AddImpulse. (DONE)
369Add PID motor for avatar movement (slow to stop, ...) (WNBD: current works ok)
370Avatar movement motor check for zero or small movement. Somehow suppress small movements
371 when avatar has stopped and is just standing. Simple test for near zero has
372 the problem of preventing starting up (increase from zero) especially when falling.
373 (DONE: avatar movement actor knows if standing on stationary object and zeros motion)
374Can the 'inTaintTime' flag be cleaned up and used? For instance, a call to
375 BSScene.TaintedObject() could immediately execute the callback if already in taint time.
376 (DONE)
377
378
379
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
index 02b03a8..d069178 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs b/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs
index b040e21..48e74eb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs
@@ -57,6 +57,8 @@ public class BasicVehicles : OpenSimTestCase
57 public void Init() 57 public void Init()
58 { 58 {
59 Dictionary<string, string> engineParams = new Dictionary<string, string>(); 59 Dictionary<string, string> engineParams = new Dictionary<string, string>();
60 engineParams.Add("VehicleEnableAngularVerticalAttraction", "true");
61 engineParams.Add("VehicleAngularVerticalAttractionAlgorithm", "1");
60 PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams); 62 PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams);
61 63
62 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere(); 64 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere();
@@ -114,21 +116,25 @@ public class BasicVehicles : OpenSimTestCase
114 // Instead the appropriate values are set and calls are made just the parts of the 116 // 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 117 // controller we want to exercise. Stepping the physics engine then applies
116 // the actions of that one feature. 118 // the actions of that one feature.
117 TestVehicle.VehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency); 119 BSDynamics vehicleActor = TestVehicle.GetVehicleActor(true /* createIfNone */);
118 TestVehicle.VehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, timeScale); 120 if (vehicleActor != null)
119 TestVehicle.VehicleActor.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 { 121 {
127 TestVehicle.VehicleActor.ForgetKnownVehicleProperties(); 122 vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency);
128 TestVehicle.VehicleActor.ComputeAngularVerticalAttraction(); 123 vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, timeScale);
129 TestVehicle.VehicleActor.PushKnownChanged(); 124 // vehicleActor.enableAngularVerticalAttraction = true;
130 125
131 PhysicsScene.Simulate(simulationTimeStep); 126 TestVehicle.IsPhysical = true;
127 PhysicsScene.ProcessTaints();
128
129 // Step the simulator a bunch of times and vertical attraction should orient the vehicle up
130 for (int ii = 0; ii < simSteps; ii++)
131 {
132 vehicleActor.ForgetKnownVehicleProperties();
133 vehicleActor.ComputeAngularVerticalAttraction();
134 vehicleActor.PushKnownChanged();
135
136 PhysicsScene.Simulate(simulationTimeStep);
137 }
132 } 138 }
133 139
134 TestVehicle.IsPhysical = false; 140 TestVehicle.IsPhysical = false;
diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
index f611b9a..b8cf624 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.6.*")] 35[assembly: AssemblyVersion("0.8.0.*")]
36 36
diff --git a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
index 5da3956..10e850e 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.6.*")] 58[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 7cd364b..44bfd42 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -415,6 +415,12 @@ namespace OpenSim.Region.Physics.Manager
415 public virtual PhysicsActor ParentActor { get { return this; } } 415 public virtual PhysicsActor ParentActor { get { return this; } }
416 416
417 417
418 // Extendable interface for new, physics engine specific operations
419 public virtual object Extension(string pFunct, params object[] pParams)
420 {
421 // A NOP of the physics engine does not implement this feature
422 return null;
423 }
418 } 424 }
419 425
420 public class NullPhysicsActor : PhysicsActor 426 public class NullPhysicsActor : PhysicsActor
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index 20a70b4..dd9bbc1 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -25,10 +25,13 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
31
30using log4net; 32using log4net;
31using Nini.Config; 33using Nini.Config;
34
32using OpenSim.Framework; 35using OpenSim.Framework;
33using OpenMetaverse; 36using OpenMetaverse;
34 37
@@ -386,5 +389,12 @@ namespace OpenSim.Region.Physics.Manager
386 { 389 {
387 return 0; 390 return 0;
388 } 391 }
392
393 // Extendable interface for new, physics engine specific operations
394 public virtual object Extension(string pFunct, params object[] pParams)
395 {
396 // A NOP if the extension thing is not implemented by the physics engine
397 return null;
398 }
389 } 399 }
390} 400}
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index d181b78..6938e55 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -40,7 +40,6 @@ using log4net;
40using Nini.Config; 40using Nini.Config;
41using System.Reflection; 41using System.Reflection;
42using System.IO; 42using System.IO;
43using ComponentAce.Compression.Libs.zlib;
44 43
45namespace OpenSim.Region.Physics.Meshing 44namespace OpenSim.Region.Physics.Meshing
46{ 45{
@@ -64,6 +63,7 @@ namespace OpenSim.Region.Physics.Meshing
64 public class Meshmerizer : IMesher 63 public class Meshmerizer : IMesher
65 { 64 {
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
66 private static string LogHeader = "[MESH]";
67 67
68 // Setting baseDir to a path will enable the dumping of raw files 68 // Setting baseDir to a path will enable the dumping of raw files
69 // raw files can be imported by blender so a visual inspection of the results can be done 69 // raw files can be imported by blender so a visual inspection of the results can be done
@@ -72,6 +72,8 @@ namespace OpenSim.Region.Physics.Meshing
72#else 72#else
73 private const string baseDir = null; //"rawFiles"; 73 private const string baseDir = null; //"rawFiles";
74#endif 74#endif
75 // If 'true', lots of DEBUG logging of asset parsing details
76 private bool debugDetail = false;
75 77
76 private bool cacheSculptMaps = true; 78 private bool cacheSculptMaps = true;
77 private string decodedSculptMapPath = null; 79 private string decodedSculptMapPath = null;
@@ -79,6 +81,9 @@ namespace OpenSim.Region.Physics.Meshing
79 81
80 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh 82 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
81 83
84 private List<List<Vector3>> mConvexHulls = null;
85 private List<Vector3> mBoundingHull = null;
86
82 private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); 87 private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
83 88
84 public Meshmerizer(IConfigSource config) 89 public Meshmerizer(IConfigSource config)
@@ -88,8 +93,11 @@ namespace OpenSim.Region.Physics.Meshing
88 93
89 decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); 94 decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
90 cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); 95 cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
91 if(mesh_config != null) 96 if (mesh_config != null)
97 {
92 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); 98 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
99 debugDetail = mesh_config.GetBoolean("LogMeshDetails", debugDetail);
100 }
93 101
94 try 102 try
95 { 103 {
@@ -319,6 +327,9 @@ namespace OpenSim.Region.Physics.Meshing
319 faces = new List<Face>(); 327 faces = new List<Face>();
320 OSD meshOsd = null; 328 OSD meshOsd = null;
321 329
330 mConvexHulls = null;
331 mBoundingHull = null;
332
322 if (primShape.SculptData.Length <= 0) 333 if (primShape.SculptData.Length <= 0)
323 { 334 {
324 // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this 335 // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this
@@ -355,9 +366,139 @@ namespace OpenSim.Region.Physics.Meshing
355 OSDMap physicsParms = null; 366 OSDMap physicsParms = null;
356 OSDMap map = (OSDMap)meshOsd; 367 OSDMap map = (OSDMap)meshOsd;
357 if (map.ContainsKey("physics_shape")) 368 if (map.ContainsKey("physics_shape"))
369 {
358 physicsParms = (OSDMap)map["physics_shape"]; // old asset format 370 physicsParms = (OSDMap)map["physics_shape"]; // old asset format
371 if (debugDetail) m_log.DebugFormat("{0} prim='{1}': using 'physics_shape' mesh data", LogHeader, primName);
372 }
359 else if (map.ContainsKey("physics_mesh")) 373 else if (map.ContainsKey("physics_mesh"))
374 {
360 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format 375 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
376 if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'physics_mesh' mesh data", LogHeader, primName);
377 }
378 else if (map.ContainsKey("medium_lod"))
379 {
380 physicsParms = (OSDMap)map["medium_lod"]; // if no physics mesh, try to fall back to medium LOD display mesh
381 if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'medium_lod' mesh data", LogHeader, primName);
382 }
383 else if (map.ContainsKey("high_lod"))
384 {
385 physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :)
386 if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'high_lod' mesh data", LogHeader, primName);
387 }
388
389 if (map.ContainsKey("physics_convex"))
390 { // pull this out also in case physics engine can use it
391 OSD convexBlockOsd = null;
392 try
393 {
394 OSDMap convexBlock = (OSDMap)map["physics_convex"];
395 {
396 int convexOffset = convexBlock["offset"].AsInteger() + (int)start;
397 int convexSize = convexBlock["size"].AsInteger();
398
399 byte[] convexBytes = new byte[convexSize];
400
401 System.Buffer.BlockCopy(primShape.SculptData, convexOffset, convexBytes, 0, convexSize);
402
403 try
404 {
405 convexBlockOsd = DecompressOsd(convexBytes);
406 }
407 catch (Exception e)
408 {
409 m_log.ErrorFormat("{0} prim='{1}': exception decoding convex block: {2}", LogHeader, primName, e);
410 //return false;
411 }
412 }
413
414 if (convexBlockOsd != null && convexBlockOsd is OSDMap)
415 {
416 convexBlock = convexBlockOsd as OSDMap;
417
418 if (debugDetail)
419 {
420 string keys = LogHeader + " keys found in convexBlock: ";
421 foreach (KeyValuePair<string, OSD> kvp in convexBlock)
422 keys += "'" + kvp.Key + "' ";
423 m_log.Debug(keys);
424 }
425
426 Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f);
427 if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3();
428 Vector3 max = new Vector3(0.5f, 0.5f, 0.5f);
429 if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3();
430
431 List<Vector3> boundingHull = null;
432
433 if (convexBlock.ContainsKey("BoundingVerts"))
434 {
435 byte[] boundingVertsBytes = convexBlock["BoundingVerts"].AsBinary();
436 boundingHull = new List<Vector3>();
437 for (int i = 0; i < boundingVertsBytes.Length; )
438 {
439 ushort uX = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
440 ushort uY = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
441 ushort uZ = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
442
443 Vector3 pos = new Vector3(
444 Utils.UInt16ToFloat(uX, min.X, max.X),
445 Utils.UInt16ToFloat(uY, min.Y, max.Y),
446 Utils.UInt16ToFloat(uZ, min.Z, max.Z)
447 );
448
449 boundingHull.Add(pos);
450 }
451
452 mBoundingHull = boundingHull;
453 if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed bounding hull. nVerts={2}", LogHeader, primName, mBoundingHull.Count);
454 }
455
456 if (convexBlock.ContainsKey("HullList"))
457 {
458 byte[] hullList = convexBlock["HullList"].AsBinary();
459
460 byte[] posBytes = convexBlock["Positions"].AsBinary();
461
462 List<List<Vector3>> hulls = new List<List<Vector3>>();
463 int posNdx = 0;
464
465 foreach (byte cnt in hullList)
466 {
467 int count = cnt == 0 ? 256 : cnt;
468 List<Vector3> hull = new List<Vector3>();
469
470 for (int i = 0; i < count; i++)
471 {
472 ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
473 ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
474 ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
475
476 Vector3 pos = new Vector3(
477 Utils.UInt16ToFloat(uX, min.X, max.X),
478 Utils.UInt16ToFloat(uY, min.Y, max.Y),
479 Utils.UInt16ToFloat(uZ, min.Z, max.Z)
480 );
481
482 hull.Add(pos);
483 }
484
485 hulls.Add(hull);
486 }
487
488 mConvexHulls = hulls;
489 if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed hulls. nHulls={2}", LogHeader, primName, mConvexHulls.Count);
490 }
491 else
492 {
493 if (debugDetail) m_log.DebugFormat("{0} prim='{1}' has physics_convex but no HullList", LogHeader, primName);
494 }
495 }
496 }
497 catch (Exception e)
498 {
499 m_log.WarnFormat("{0} exception decoding convex block: {1}", LogHeader, e);
500 }
501 }
361 502
362 if (physicsParms == null) 503 if (physicsParms == null)
363 { 504 {
@@ -374,34 +515,14 @@ namespace OpenSim.Region.Physics.Meshing
374 OSD decodedMeshOsd = new OSD(); 515 OSD decodedMeshOsd = new OSD();
375 byte[] meshBytes = new byte[physSize]; 516 byte[] meshBytes = new byte[physSize];
376 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); 517 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
377// byte[] decompressed = new byte[physSize * 5]; 518 // byte[] decompressed = new byte[physSize * 5];
378 try 519 try
379 { 520 {
380 using (MemoryStream inMs = new MemoryStream(meshBytes)) 521 decodedMeshOsd = DecompressOsd(meshBytes);
381 {
382 using (MemoryStream outMs = new MemoryStream())
383 {
384 using (ZOutputStream zOut = new ZOutputStream(outMs))
385 {
386 byte[] readBuffer = new byte[2048];
387 int readLen = 0;
388 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
389 {
390 zOut.Write(readBuffer, 0, readLen);
391 }
392 zOut.Flush();
393 outMs.Seek(0, SeekOrigin.Begin);
394
395 byte[] decompressedBuf = outMs.GetBuffer();
396
397 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
398 }
399 }
400 }
401 } 522 }
402 catch (Exception e) 523 catch (Exception e)
403 { 524 {
404 m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); 525 m_log.ErrorFormat("{0} prim='{1}': exception decoding physical mesh: {2}", LogHeader, primName, e);
405 return false; 526 return false;
406 } 527 }
407 528
@@ -410,7 +531,7 @@ namespace OpenSim.Region.Physics.Meshing
410 // physics_shape is an array of OSDMaps, one for each submesh 531 // physics_shape is an array of OSDMaps, one for each submesh
411 if (decodedMeshOsd is OSDArray) 532 if (decodedMeshOsd is OSDArray)
412 { 533 {
413// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); 534 // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
414 535
415 decodedMeshOsdArray = (OSDArray)decodedMeshOsd; 536 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
416 foreach (OSD subMeshOsd in decodedMeshOsdArray) 537 foreach (OSD subMeshOsd in decodedMeshOsdArray)
@@ -418,6 +539,9 @@ namespace OpenSim.Region.Physics.Meshing
418 if (subMeshOsd is OSDMap) 539 if (subMeshOsd is OSDMap)
419 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); 540 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
420 } 541 }
542 if (debugDetail)
543 m_log.DebugFormat("{0} {1}: mesh decoded. offset={2}, size={3}, nCoords={4}, nFaces={5}",
544 LogHeader, primName, physOffset, physSize, coords.Count, faces.Count);
421 } 545 }
422 } 546 }
423 547
@@ -425,6 +549,42 @@ namespace OpenSim.Region.Physics.Meshing
425 } 549 }
426 550
427 /// <summary> 551 /// <summary>
552 /// decompresses a gzipped OSD object
553 /// </summary>
554 /// <param name="decodedOsd"></param> the OSD object
555 /// <param name="meshBytes"></param>
556 /// <returns></returns>
557 private static OSD DecompressOsd(byte[] meshBytes)
558 {
559 OSD decodedOsd = null;
560
561 using (MemoryStream inMs = new MemoryStream(meshBytes))
562 {
563 using (MemoryStream outMs = new MemoryStream())
564 {
565 using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress))
566 {
567 byte[] readBuffer = new byte[2048];
568 inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header
569 int readLen = 0;
570
571 while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
572 outMs.Write(readBuffer, 0, readLen);
573
574 outMs.Flush();
575
576 outMs.Seek(0, SeekOrigin.Begin);
577
578 byte[] decompressedBuf = outMs.GetBuffer();
579
580 decodedOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
581 }
582 }
583 }
584 return decodedOsd;
585 }
586
587 /// <summary>
428 /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim. 588 /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim.
429 /// </summary> 589 /// </summary>
430 /// <param name="primName"></param> 590 /// <param name="primName"></param>
@@ -469,10 +629,11 @@ namespace OpenSim.Region.Physics.Meshing
469 629
470 try 630 try
471 { 631 {
472 OpenMetaverse.Imaging.ManagedImage unusedData; 632 OpenMetaverse.Imaging.ManagedImage managedImage;
473 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata); 633
634 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out managedImage);
474 635
475 if (idata == null) 636 if (managedImage == null)
476 { 637 {
477 // In some cases it seems that the decode can return a null bitmap without throwing 638 // In some cases it seems that the decode can return a null bitmap without throwing
478 // an exception 639 // an exception
@@ -481,9 +642,12 @@ namespace OpenSim.Region.Physics.Meshing
481 return false; 642 return false;
482 } 643 }
483 644
484 unusedData = null; 645 if ((managedImage.Channels & OpenMetaverse.Imaging.ManagedImage.ImageChannels.Alpha) != 0)
646 managedImage.ConvertChannels(managedImage.Channels & ~OpenMetaverse.Imaging.ManagedImage.ImageChannels.Alpha);
485 647
486 //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); 648 Bitmap imgData = OpenMetaverse.Imaging.LoadTGAClass.LoadTGA(new MemoryStream(managedImage.ExportTGA()));
649 idata = (Image)imgData;
650 managedImage = null;
487 651
488 if (cacheSculptMaps) 652 if (cacheSculptMaps)
489 { 653 {
@@ -700,6 +864,45 @@ namespace OpenSim.Region.Physics.Meshing
700 return true; 864 return true;
701 } 865 }
702 866
867 /// <summary>
868 /// temporary prototype code - please do not use until the interface has been finalized!
869 /// </summary>
870 /// <param name="size">value to scale the hull points by</param>
871 /// <returns>a list of vertices in the bounding hull if it exists and has been successfully decoded, otherwise null</returns>
872 public List<Vector3> GetBoundingHull(Vector3 size)
873 {
874 if (mBoundingHull == null)
875 return null;
876
877 List<Vector3> verts = new List<Vector3>();
878 foreach (var vert in mBoundingHull)
879 verts.Add(vert * size);
880
881 return verts;
882 }
883
884 /// <summary>
885 /// temporary prototype code - please do not use until the interface has been finalized!
886 /// </summary>
887 /// <param name="size">value to scale the hull points by</param>
888 /// <returns>a list of hulls if they exist and have been successfully decoded, otherwise null</returns>
889 public List<List<Vector3>> GetConvexHulls(Vector3 size)
890 {
891 if (mConvexHulls == null)
892 return null;
893
894 List<List<Vector3>> hulls = new List<List<Vector3>>();
895 foreach (var hull in mConvexHulls)
896 {
897 List<Vector3> verts = new List<Vector3>();
898 foreach (var vert in hull)
899 verts.Add(vert * size);
900 hulls.Add(verts);
901 }
902
903 return hulls;
904 }
905
703 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 906 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
704 { 907 {
705 return CreateMesh(primName, primShape, size, lod, false, true); 908 return CreateMesh(primName, primShape, size, lod, false, true);
diff --git a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
index 3de061a..8542753 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
index f477ed1..288cab5 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.6.*")] 58[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index d09aa62..b4b7e7f 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -108,7 +108,6 @@ namespace OpenSim.Region.Physics.OdePlugin
108 private Vector3 m_taintAngularLock = Vector3.One; 108 private Vector3 m_taintAngularLock = Vector3.One;
109 private IntPtr Amotor = IntPtr.Zero; 109 private IntPtr Amotor = IntPtr.Zero;
110 110
111 private object m_assetsLock = new object();
112 private bool m_assetFailed = false; 111 private bool m_assetFailed = false;
113 112
114 private Vector3 m_PIDTarget; 113 private Vector3 m_PIDTarget;
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 07663b3..7e652fc 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -46,7 +46,7 @@ namespace OpenSim.Region.Physics.OdePlugin
46 /// </summary> 46 /// </summary>
47 public class OdePlugin : IPhysicsPlugin 47 public class OdePlugin : IPhysicsPlugin
48 { 48 {
49 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 49// private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 private OdeScene m_scene; 51 private OdeScene m_scene;
52 52
diff --git a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
index 4289863..83be103 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.6.*")] 58[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
index 86a3101..c341dfd 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
index f424e7f..83732e2 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
@@ -51,7 +51,8 @@ namespace OpenSim.Region.RegionCombinerModule
51 m_virtScene.UnSubscribeToClientPrimEvents(client); 51 m_virtScene.UnSubscribeToClientPrimEvents(client);
52 m_virtScene.UnSubscribeToClientPrimRezEvents(client); 52 m_virtScene.UnSubscribeToClientPrimRezEvents(client);
53 m_virtScene.UnSubscribeToClientInventoryEvents(client); 53 m_virtScene.UnSubscribeToClientInventoryEvents(client);
54 ((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client); 54 if(m_virtScene.AttachmentsModule != null)
55 ((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client);
55 //m_virtScene.UnSubscribeToClientTeleportEvents(client); 56 //m_virtScene.UnSubscribeToClientTeleportEvents(client);
56 m_virtScene.UnSubscribeToClientScriptEvents(client); 57 m_virtScene.UnSubscribeToClientScriptEvents(client);
57 58
@@ -66,7 +67,8 @@ namespace OpenSim.Region.RegionCombinerModule
66 client.OnRezObject += LocalRezObject; 67 client.OnRezObject += LocalRezObject;
67 68
68 m_rootScene.SubscribeToClientInventoryEvents(client); 69 m_rootScene.SubscribeToClientInventoryEvents(client);
69 ((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client); 70 if (m_rootScene.AttachmentsModule != null)
71 ((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client);
70 //m_rootScene.SubscribeToClientTeleportEvents(client); 72 //m_rootScene.SubscribeToClientTeleportEvents(client);
71 m_rootScene.SubscribeToClientScriptEvents(client); 73 m_rootScene.SubscribeToClientScriptEvents(client);
72 74
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
index b4abc1d..4bf2a82 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
@@ -27,6 +27,8 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
30using OpenMetaverse; 32using OpenMetaverse;
31using OpenSim.Framework; 33using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
@@ -34,10 +36,10 @@ using OpenSim.Region.CoreModules.World.Land;
34 36
35namespace OpenSim.Region.RegionCombinerModule 37namespace OpenSim.Region.RegionCombinerModule
36{ 38{
37public class RegionCombinerLargeLandChannel : ILandChannel 39 public class RegionCombinerLargeLandChannel : ILandChannel
38 { 40 {
39 // private static readonly ILog m_log = 41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42
41 private RegionData RegData; 43 private RegionData RegData;
42 private ILandChannel RootRegionLandChannel; 44 private ILandChannel RootRegionLandChannel;
43 private readonly List<RegionData> RegionConnections; 45 private readonly List<RegionData> RegionConnections;
@@ -75,40 +77,51 @@ public class RegionCombinerLargeLandChannel : ILandChannel
75 77
76 public ILandObject GetLandObject(int x, int y) 78 public ILandObject GetLandObject(int x, int y)
77 { 79 {
78 //m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y); 80 return GetLandObject((float)x, (float)y);
79 81
80 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize) 82// m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y);
81 { 83//
82 return RootRegionLandChannel.GetLandObject(x, y); 84// if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
83 } 85// {
84 else 86// return RootRegionLandChannel.GetLandObject(x, y);
85 { 87// }
86 int offsetX = (x / (int)Constants.RegionSize); 88// else
87 int offsetY = (y / (int)Constants.RegionSize); 89// {
88 offsetX *= (int)Constants.RegionSize; 90// int offsetX = (x / (int)Constants.RegionSize);
89 offsetY *= (int)Constants.RegionSize; 91// int offsetY = (y / (int)Constants.RegionSize);
90 92// offsetX *= (int)Constants.RegionSize;
91 foreach (RegionData regionData in RegionConnections) 93// offsetY *= (int)Constants.RegionSize;
92 { 94//
93 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY) 95// foreach (RegionData regionData in RegionConnections)
94 { 96// {
95 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY); 97// if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
96 } 98// {
97 } 99// m_log.DebugFormat(
98 ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene); 100// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
99 obj.LandData.Name = "NO LAND"; 101// regionData.RegionScene.Name, offsetX, offsetY);
100 return obj; 102//
101 } 103// return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
104// }
105// }
106// //ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
107// //obj.LandData.Name = "NO LAND";
108// //return obj;
109// }
110//
111// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
112//
113// return null;
102 } 114 }
103 115
104 public ILandObject GetLandObject(int localID) 116 public ILandObject GetLandObject(int localID)
105 { 117 {
118 // XXX: Possibly should be looking in every land channel, not just the root.
106 return RootRegionLandChannel.GetLandObject(localID); 119 return RootRegionLandChannel.GetLandObject(localID);
107 } 120 }
108 121
109 public ILandObject GetLandObject(float x, float y) 122 public ILandObject GetLandObject(float x, float y)
110 { 123 {
111 //m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y); 124// m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y);
112 125
113 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize) 126 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
114 { 127 {
@@ -125,14 +138,22 @@ public class RegionCombinerLargeLandChannel : ILandChannel
125 { 138 {
126 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY) 139 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
127 { 140 {
141// m_log.DebugFormat(
142// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
143// regionData.RegionScene.Name, offsetX, offsetY);
144
128 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY); 145 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
129 } 146 }
130 } 147 }
131 148
132 ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene); 149// ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
133 obj.LandData.Name = "NO LAND"; 150// obj.LandData.Name = "NO LAND";
134 return obj; 151// return obj;
135 } 152 }
153
154// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
155
156 return null;
136 } 157 }
137 158
138 public bool IsForcefulBansAllowed() 159 public bool IsForcefulBansAllowed()
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index 35ae44c..b9a217b 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
51 public interface IScriptWorkItem 51 public interface IScriptWorkItem
52 { 52 {
53 bool Cancel(); 53 bool Cancel();
54 void Abort(); 54 bool Abort();
55 55
56 /// <summary> 56 /// <summary>
57 /// Wait for the work item to complete. 57 /// Wait for the work item to complete.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 6879ebb..1e19032 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -37,6 +37,8 @@ using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared; 37using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 38using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
39using Timer=OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; 39using Timer=OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
40using System.Reflection;
41using log4net;
40 42
41namespace OpenSim.Region.ScriptEngine.Shared.Api 43namespace OpenSim.Region.ScriptEngine.Shared.Api
42{ 44{
@@ -45,15 +47,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
45 /// </summary> 47 /// </summary>
46 public class AsyncCommandManager 48 public class AsyncCommandManager
47 { 49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
48 private static Thread cmdHandlerThread; 52 private static Thread cmdHandlerThread;
49 private static int cmdHandlerThreadCycleSleepms; 53 private static int cmdHandlerThreadCycleSleepms;
50 54
51 private static List<IScene> m_Scenes = new List<IScene>(); 55 /// <summary>
56 /// Lock for reading/writing static components of AsyncCommandManager.
57 /// </summary>
58 /// <remarks>
59 /// This lock exists so that multiple threads from different engines and/or different copies of the same engine
60 /// are prevented from running non-thread safe code (e.g. read/write of lists) concurrently.
61 /// </remarks>
62 private static object staticLock = new object();
63
52 private static List<IScriptEngine> m_ScriptEngines = 64 private static List<IScriptEngine> m_ScriptEngines =
53 new List<IScriptEngine>(); 65 new List<IScriptEngine>();
54 66
55 public IScriptEngine m_ScriptEngine; 67 public IScriptEngine m_ScriptEngine;
56 private IScene m_Scene;
57 68
58 private static Dictionary<IScriptEngine, Dataserver> m_Dataserver = 69 private static Dictionary<IScriptEngine, Dataserver> m_Dataserver =
59 new Dictionary<IScriptEngine, Dataserver>(); 70 new Dictionary<IScriptEngine, Dataserver>();
@@ -70,67 +81,99 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
70 81
71 public Dataserver DataserverPlugin 82 public Dataserver DataserverPlugin
72 { 83 {
73 get { return m_Dataserver[m_ScriptEngine]; } 84 get
85 {
86 lock (staticLock)
87 return m_Dataserver[m_ScriptEngine];
88 }
74 } 89 }
75 90
76 public Timer TimerPlugin 91 public Timer TimerPlugin
77 { 92 {
78 get { return m_Timer[m_ScriptEngine]; } 93 get
94 {
95 lock (staticLock)
96 return m_Timer[m_ScriptEngine];
97 }
79 } 98 }
80 99
81 public HttpRequest HttpRequestPlugin 100 public HttpRequest HttpRequestPlugin
82 { 101 {
83 get { return m_HttpRequest[m_ScriptEngine]; } 102 get
103 {
104 lock (staticLock)
105 return m_HttpRequest[m_ScriptEngine];
106 }
84 } 107 }
85 108
86 public Listener ListenerPlugin 109 public Listener ListenerPlugin
87 { 110 {
88 get { return m_Listener[m_ScriptEngine]; } 111 get
112 {
113 lock (staticLock)
114 return m_Listener[m_ScriptEngine];
115 }
89 } 116 }
90 117
91 public SensorRepeat SensorRepeatPlugin 118 public SensorRepeat SensorRepeatPlugin
92 { 119 {
93 get { return m_SensorRepeat[m_ScriptEngine]; } 120 get
121 {
122 lock (staticLock)
123 return m_SensorRepeat[m_ScriptEngine];
124 }
94 } 125 }
95 126
96 public XmlRequest XmlRequestPlugin 127 public XmlRequest XmlRequestPlugin
97 { 128 {
98 get { return m_XmlRequest[m_ScriptEngine]; } 129 get
130 {
131 lock (staticLock)
132 return m_XmlRequest[m_ScriptEngine];
133 }
99 } 134 }
100 135
101 public IScriptEngine[] ScriptEngines 136 public IScriptEngine[] ScriptEngines
102 { 137 {
103 get { return m_ScriptEngines.ToArray(); } 138 get
139 {
140 lock (staticLock)
141 return m_ScriptEngines.ToArray();
142 }
104 } 143 }
105 144
106 public AsyncCommandManager(IScriptEngine _ScriptEngine) 145 public AsyncCommandManager(IScriptEngine _ScriptEngine)
107 { 146 {
108 m_ScriptEngine = _ScriptEngine; 147 m_ScriptEngine = _ScriptEngine;
109 m_Scene = m_ScriptEngine.World; 148
110 149 // If there is more than one scene in the simulator or multiple script engines are used on the same region
111 if (m_Scenes.Count == 0) 150 // then more than one thread could arrive at this block of code simultaneously. However, it cannot be
112 ReadConfig(); 151 // executed concurrently both because concurrent list operations are not thread-safe and because of other
113 152 // race conditions such as the later check of cmdHandlerThread == null.
114 if (!m_Scenes.Contains(m_Scene)) 153 lock (staticLock)
115 m_Scenes.Add(m_Scene); 154 {
116 if (!m_ScriptEngines.Contains(m_ScriptEngine)) 155 if (m_ScriptEngines.Count == 0)
117 m_ScriptEngines.Add(m_ScriptEngine); 156 ReadConfig();
118 157
119 // Create instances of all plugins 158 if (!m_ScriptEngines.Contains(m_ScriptEngine))
120 if (!m_Dataserver.ContainsKey(m_ScriptEngine)) 159 m_ScriptEngines.Add(m_ScriptEngine);
121 m_Dataserver[m_ScriptEngine] = new Dataserver(this); 160
122 if (!m_Timer.ContainsKey(m_ScriptEngine)) 161 // Create instances of all plugins
123 m_Timer[m_ScriptEngine] = new Timer(this); 162 if (!m_Dataserver.ContainsKey(m_ScriptEngine))
124 if (!m_HttpRequest.ContainsKey(m_ScriptEngine)) 163 m_Dataserver[m_ScriptEngine] = new Dataserver(this);
125 m_HttpRequest[m_ScriptEngine] = new HttpRequest(this); 164 if (!m_Timer.ContainsKey(m_ScriptEngine))
126 if (!m_Listener.ContainsKey(m_ScriptEngine)) 165 m_Timer[m_ScriptEngine] = new Timer(this);
127 m_Listener[m_ScriptEngine] = new Listener(this); 166 if (!m_HttpRequest.ContainsKey(m_ScriptEngine))
128 if (!m_SensorRepeat.ContainsKey(m_ScriptEngine)) 167 m_HttpRequest[m_ScriptEngine] = new HttpRequest(this);
129 m_SensorRepeat[m_ScriptEngine] = new SensorRepeat(this); 168 if (!m_Listener.ContainsKey(m_ScriptEngine))
130 if (!m_XmlRequest.ContainsKey(m_ScriptEngine)) 169 m_Listener[m_ScriptEngine] = new Listener(this);
131 m_XmlRequest[m_ScriptEngine] = new XmlRequest(this); 170 if (!m_SensorRepeat.ContainsKey(m_ScriptEngine))
132 171 m_SensorRepeat[m_ScriptEngine] = new SensorRepeat(this);
133 StartThread(); 172 if (!m_XmlRequest.ContainsKey(m_ScriptEngine))
173 m_XmlRequest[m_ScriptEngine] = new XmlRequest(this);
174
175 StartThread();
176 }
134 } 177 }
135 178
136 private static void StartThread() 179 private static void StartThread()
@@ -179,42 +222,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
179 { 222 {
180 try 223 try
181 { 224 {
182 while (true) 225 Thread.Sleep(cmdHandlerThreadCycleSleepms);
183 {
184 Thread.Sleep(cmdHandlerThreadCycleSleepms);
185 226
186 DoOneCmdHandlerPass(); 227 DoOneCmdHandlerPass();
187 228
188 Watchdog.UpdateThread(); 229 Watchdog.UpdateThread();
189 }
190 } 230 }
191 catch 231 catch (Exception e)
192 { 232 {
233 m_log.Error("[ASYNC COMMAND MANAGER]: Exception in command handler pass: ", e);
193 } 234 }
194 } 235 }
195 } 236 }
196 237
197 private static void DoOneCmdHandlerPass() 238 private static void DoOneCmdHandlerPass()
198 { 239 {
199 // Check HttpRequests 240 lock (staticLock)
200 m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests(); 241 {
242 // Check HttpRequests
243 m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests();
201 244
202 // Check XMLRPCRequests 245 // Check XMLRPCRequests
203 m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests(); 246 m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests();
204 247
205 foreach (IScriptEngine s in m_ScriptEngines) 248 foreach (IScriptEngine s in m_ScriptEngines)
206 { 249 {
207 // Check Listeners 250 // Check Listeners
208 m_Listener[s].CheckListeners(); 251 m_Listener[s].CheckListeners();
209 252
210 // Check timers 253 // Check timers
211 m_Timer[s].CheckTimerEvents(); 254 m_Timer[s].CheckTimerEvents();
212 255
213 // Check Sensors 256 // Check Sensors
214 m_SensorRepeat[s].CheckSenseRepeaterEvents(); 257 m_SensorRepeat[s].CheckSenseRepeaterEvents();
215 258
216 // Check dataserver 259 // Check dataserver
217 m_Dataserver[s].ExpireRequests(); 260 m_Dataserver[s].ExpireRequests();
261 }
218 } 262 }
219 } 263 }
220 264
@@ -226,31 +270,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
226 public static void RemoveScript(IScriptEngine engine, uint localID, UUID itemID) 270 public static void RemoveScript(IScriptEngine engine, uint localID, UUID itemID)
227 { 271 {
228 // Remove a specific script 272 // Remove a specific script
273// m_log.DebugFormat("[ASYNC COMMAND MANAGER]: Removing facilities for script {0}", itemID);
229 274
230 // Remove dataserver events 275 lock (staticLock)
231 m_Dataserver[engine].RemoveEvents(localID, itemID); 276 {
277 // Remove dataserver events
278 m_Dataserver[engine].RemoveEvents(localID, itemID);
232 279
233 // Remove from: Timers 280 // Remove from: Timers
234 m_Timer[engine].UnSetTimerEvents(localID, itemID); 281 m_Timer[engine].UnSetTimerEvents(localID, itemID);
235 282
236 // Remove from: HttpRequest 283 // Remove from: HttpRequest
237 IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface<IHttpRequestModule>(); 284 IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface<IHttpRequestModule>();
238 if (iHttpReq != null) 285 if (iHttpReq != null)
239 iHttpReq.StopHttpRequest(localID, itemID); 286 iHttpReq.StopHttpRequest(localID, itemID);
240 287
241 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>(); 288 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
242 if (comms != null) 289 if (comms != null)
243 comms.DeleteListener(itemID); 290 comms.DeleteListener(itemID);
244 291
245 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>(); 292 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
246 if (xmlrpc != null) 293 if (xmlrpc != null)
247 { 294 {
248 xmlrpc.DeleteChannels(itemID); 295 xmlrpc.DeleteChannels(itemID);
249 xmlrpc.CancelSRDRequests(itemID); 296 xmlrpc.CancelSRDRequests(itemID);
250 } 297 }
251 298
252 // Remove Sensors 299 // Remove Sensors
253 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID); 300 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
301 }
254 } 302 }
255 303
256 /// <summary> 304 /// <summary>
@@ -260,10 +308,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
260 /// <returns></returns> 308 /// <returns></returns>
261 public static SensorRepeat GetSensorRepeatPlugin(IScriptEngine engine) 309 public static SensorRepeat GetSensorRepeatPlugin(IScriptEngine engine)
262 { 310 {
263 if (m_SensorRepeat.ContainsKey(engine)) 311 lock (staticLock)
264 return m_SensorRepeat[engine]; 312 {
265 else 313 if (m_SensorRepeat.ContainsKey(engine))
266 return null; 314 return m_SensorRepeat[engine];
315 else
316 return null;
317 }
267 } 318 }
268 319
269 /// <summary> 320 /// <summary>
@@ -273,10 +324,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
273 /// <returns></returns> 324 /// <returns></returns>
274 public static Dataserver GetDataserverPlugin(IScriptEngine engine) 325 public static Dataserver GetDataserverPlugin(IScriptEngine engine)
275 { 326 {
276 if (m_Dataserver.ContainsKey(engine)) 327 lock (staticLock)
277 return m_Dataserver[engine]; 328 {
278 else 329 if (m_Dataserver.ContainsKey(engine))
279 return null; 330 return m_Dataserver[engine];
331 else
332 return null;
333 }
280 } 334 }
281 335
282 /// <summary> 336 /// <summary>
@@ -286,10 +340,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
286 /// <returns></returns> 340 /// <returns></returns>
287 public static Timer GetTimerPlugin(IScriptEngine engine) 341 public static Timer GetTimerPlugin(IScriptEngine engine)
288 { 342 {
289 if (m_Timer.ContainsKey(engine)) 343 lock (staticLock)
290 return m_Timer[engine]; 344 {
291 else 345 if (m_Timer.ContainsKey(engine))
292 return null; 346 return m_Timer[engine];
347 else
348 return null;
349 }
293 } 350 }
294 351
295 /// <summary> 352 /// <summary>
@@ -299,10 +356,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
299 /// <returns></returns> 356 /// <returns></returns>
300 public static Listener GetListenerPlugin(IScriptEngine engine) 357 public static Listener GetListenerPlugin(IScriptEngine engine)
301 { 358 {
302 if (m_Listener.ContainsKey(engine)) 359 lock (staticLock)
303 return m_Listener[engine]; 360 {
304 else 361 if (m_Listener.ContainsKey(engine))
305 return null; 362 return m_Listener[engine];
363 else
364 return null;
365 }
306 } 366 }
307 367
308 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID) 368 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID)
@@ -332,28 +392,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
332 { 392 {
333 List<Object> data = new List<Object>(); 393 List<Object> data = new List<Object>();
334 394
335 Object[] listeners = m_Listener[engine].GetSerializationData(itemID); 395 lock (staticLock)
336 if (listeners.Length > 0)
337 { 396 {
338 data.Add("listener"); 397 Object[] listeners = m_Listener[engine].GetSerializationData(itemID);
339 data.Add(listeners.Length); 398 if (listeners.Length > 0)
340 data.AddRange(listeners); 399 {
341 } 400 data.Add("listener");
401 data.Add(listeners.Length);
402 data.AddRange(listeners);
403 }
342 404
343 Object[] timers=m_Timer[engine].GetSerializationData(itemID); 405 Object[] timers=m_Timer[engine].GetSerializationData(itemID);
344 if (timers.Length > 0) 406 if (timers.Length > 0)
345 { 407 {
346 data.Add("timer"); 408 data.Add("timer");
347 data.Add(timers.Length); 409 data.Add(timers.Length);
348 data.AddRange(timers); 410 data.AddRange(timers);
349 } 411 }
350 412
351 Object[] sensors = m_SensorRepeat[engine].GetSerializationData(itemID); 413 Object[] sensors = m_SensorRepeat[engine].GetSerializationData(itemID);
352 if (sensors.Length > 0) 414 if (sensors.Length > 0)
353 { 415 {
354 data.Add("sensor"); 416 data.Add("sensor");
355 data.Add(sensors.Length); 417 data.Add(sensors.Length);
356 data.AddRange(sensors); 418 data.AddRange(sensors);
419 }
357 } 420 }
358 421
359 return data.ToArray(); 422 return data.ToArray();
@@ -378,41 +441,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
378 441
379 idx+=len; 442 idx+=len;
380 443
444 lock (staticLock)
445 {
381 switch (type) 446 switch (type)
382 { 447 {
383 case "listener": 448 case "listener":
384 m_Listener[engine].CreateFromData(localID, itemID, 449 m_Listener[engine].CreateFromData(localID, itemID,
385 hostID, item); 450 hostID, item);
386 break; 451 break;
387 case "timer": 452 case "timer":
388 m_Timer[engine].CreateFromData(localID, itemID, 453 m_Timer[engine].CreateFromData(localID, itemID,
389 hostID, item); 454 hostID, item);
390 break; 455 break;
391 case "sensor": 456 case "sensor":
392 m_SensorRepeat[engine].CreateFromData(localID, 457 m_SensorRepeat[engine].CreateFromData(localID,
393 itemID, hostID, item); 458 itemID, hostID, item);
394 break; 459 break;
460 }
395 } 461 }
396 } 462 }
397 } 463 }
398 } 464 }
399
400 #region Check llRemoteData channels
401
402 #endregion
403
404 #region Check llListeners
405
406 #endregion
407
408 /// <summary>
409 /// If set to true then threads and stuff should try to make a graceful exit
410 /// </summary>
411 public bool PleaseShutdown
412 {
413 get { return _PleaseShutdown; }
414 set { _PleaseShutdown = value; }
415 }
416 private bool _PleaseShutdown = false;
417 } 465 }
418} 466}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 3f0af6d..916d841 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -1664,6 +1664,75 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1664 m_host.SetFaceColorAlpha(face, color, null); 1664 m_host.SetFaceColorAlpha(face, color, null);
1665 } 1665 }
1666 1666
1667 /*
1668 public void llSetContentType(LSL_Key id, LSL_Integer type)
1669 {
1670 m_host.AddScriptLPS(1);
1671
1672 if (m_UrlModule == null)
1673 return;
1674
1675 // Make sure the content type is text/plain to start with
1676 m_UrlModule.HttpContentType(new UUID(id), "text/plain");
1677
1678 // Is the object owner online and in the region
1679 ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID);
1680 if (agent == null || agent.IsChildAgent)
1681 return; // Fail if the owner is not in the same region
1682
1683 // Is it the embeded browser?
1684 string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent");
1685 if (userAgent.IndexOf("SecondLife") < 0)
1686 return; // Not the embedded browser. Is this check good enough?
1687
1688 // Use the IP address of the client and check against the request
1689 // seperate logins from the same IP will allow all of them to get non-text/plain as long
1690 // as the owner is in the region. Same as SL!
1691 string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString();
1692 string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr");
1693 //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'");
1694 if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "")
1695 return;
1696 if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "")
1697 return;
1698
1699 // If the request isnt from the same IP address then the request cannot be from the owner
1700 if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim()))
1701 return;
1702
1703 switch (type)
1704 {
1705 case ScriptBaseClass.CONTENT_TYPE_HTML:
1706 m_UrlModule.HttpContentType(new UUID(id), "text/html");
1707 break;
1708 case ScriptBaseClass.CONTENT_TYPE_XML:
1709 m_UrlModule.HttpContentType(new UUID(id), "application/xml");
1710 break;
1711 case ScriptBaseClass.CONTENT_TYPE_XHTML:
1712 m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml");
1713 break;
1714 case ScriptBaseClass.CONTENT_TYPE_ATOM:
1715 m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml");
1716 break;
1717 case ScriptBaseClass.CONTENT_TYPE_JSON:
1718 m_UrlModule.HttpContentType(new UUID(id), "application/json");
1719 break;
1720 case ScriptBaseClass.CONTENT_TYPE_LLSD:
1721 m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml");
1722 break;
1723 case ScriptBaseClass.CONTENT_TYPE_FORM:
1724 m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded");
1725 break;
1726 case ScriptBaseClass.CONTENT_TYPE_RSS:
1727 m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml");
1728 break;
1729 default:
1730 m_UrlModule.HttpContentType(new UUID(id), "text/plain");
1731 break;
1732 }
1733 }
1734 */
1735
1667 public void SetTexGen(SceneObjectPart part, int face,int style) 1736 public void SetTexGen(SceneObjectPart part, int face,int style)
1668 { 1737 {
1669 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 1738 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
@@ -2772,9 +2841,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2772 // send the sound, once, to all clients in range 2841 // send the sound, once, to all clients in range
2773 if (m_SoundModule != null) 2842 if (m_SoundModule != null)
2774 { 2843 {
2775 m_SoundModule.SendSound(m_host.UUID, 2844 m_SoundModule.SendSound(
2776 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0, 2845 m_host.UUID,
2777 0, false, false); 2846 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
2847 volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None,
2848 0, false, false);
2778 } 2849 }
2779 } 2850 }
2780 2851
@@ -3176,46 +3247,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3176 // need the magnitude later 3247 // need the magnitude later
3177 // float velmag = (float)Util.GetMagnitude(llvel); 3248 // float velmag = (float)Util.GetMagnitude(llvel);
3178 3249
3179 SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); 3250 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
3180 3251
3181 // If either of these are null, then there was an unknown error. 3252 // If either of these are null, then there was an unknown error.
3182 if (new_group == null) 3253 if (new_groups == null)
3183 return; 3254 return;
3184 3255
3185 // objects rezzed with this method are die_at_edge by default. 3256 foreach (SceneObjectGroup group in new_groups)
3186 new_group.RootPart.SetDieAtEdge(true); 3257 {
3187 3258 // objects rezzed with this method are die_at_edge by default.
3188 new_group.ResumeScripts(); 3259 group.RootPart.SetDieAtEdge(true);
3189 3260
3190 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3261 group.ResumeScripts();
3191 "object_rez", new Object[] {
3192 new LSL_String(
3193 new_group.RootPart.UUID.ToString()) },
3194 new DetectParams[0]));
3195 3262
3196 // do recoil 3263 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
3197 SceneObjectGroup hostgrp = m_host.ParentGroup; 3264 "object_rez", new Object[] {
3198 if (hostgrp == null) 3265 new LSL_String(
3199 return; 3266 group.RootPart.UUID.ToString()) },
3267 new DetectParams[0]));
3200 3268
3201 if (hostgrp.IsAttachment) // don't recoil avatars 3269 float groupmass = group.GetMass();
3202 return;
3203 3270
3204 PhysicsActor pa = new_group.RootPart.PhysActor; 3271 PhysicsActor pa = group.RootPart.PhysActor;
3205 3272
3206 //Recoil. 3273 //Recoil.
3207 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3274 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3208 {
3209 float groupmass = new_group.GetMass();
3210 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3211 if (recoil != Vector3.Zero)
3212 { 3275 {
3213 llApplyImpulse(recoil, 0); 3276 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3277 if (recoil != Vector3.Zero)
3278 {
3279 llApplyImpulse(recoil, 0);
3280 }
3214 } 3281 }
3282 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3215 } 3283 }
3216 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3217 return; 3284 return;
3218
3219 }); 3285 });
3220 3286
3221 //ScriptSleep((int)((groupmass * velmag) / 10)); 3287 //ScriptSleep((int)((groupmass * velmag) / 10));
@@ -4746,6 +4812,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4746 UUID av = new UUID(); 4812 UUID av = new UUID();
4747 if (!UUID.TryParse(agent,out av)) 4813 if (!UUID.TryParse(agent,out av))
4748 { 4814 {
4815 LSLError("First parameter to llTextBox needs to be a key");
4749 return; 4816 return;
4750 } 4817 }
4751 4818
@@ -5108,6 +5175,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5108 5175
5109 s = Math.Cos(angle * 0.5); 5176 s = Math.Cos(angle * 0.5);
5110 t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs 5177 t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs
5178 axis = LSL_Vector.Norm(axis);
5111 x = axis.x * t; 5179 x = axis.x * t;
5112 y = axis.y * t; 5180 y = axis.y * t;
5113 z = axis.z * t; 5181 z = axis.z * t;
@@ -5115,41 +5183,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5115 return new LSL_Rotation(x,y,z,s); 5183 return new LSL_Rotation(x,y,z,s);
5116 } 5184 }
5117 5185
5118 5186 /// <summary>
5119 // Xantor 29/apr/2008 5187 /// Returns the axis of rotation for a quaternion
5120 // converts a Quaternion to X,Y,Z axis rotations 5188 /// </summary>
5189 /// <returns></returns>
5190 /// <param name='rot'></param>
5121 public LSL_Vector llRot2Axis(LSL_Rotation rot) 5191 public LSL_Vector llRot2Axis(LSL_Rotation rot)
5122 { 5192 {
5123 m_host.AddScriptLPS(1); 5193 m_host.AddScriptLPS(1);
5124 double x,y,z;
5125 5194
5126 if (rot.s > 1) // normalization needed 5195 if (Math.Abs(rot.s) > 1) // normalization needed
5127 { 5196 rot.Normalize();
5128 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
5129 rot.z * rot.z + rot.s * rot.s);
5130
5131 rot.x /= length;
5132 rot.y /= length;
5133 rot.z /= length;
5134 rot.s /= length;
5135
5136 }
5137 5197
5138 // double angle = 2 * Math.Acos(rot.s);
5139 double s = Math.Sqrt(1 - rot.s * rot.s); 5198 double s = Math.Sqrt(1 - rot.s * rot.s);
5140 if (s < 0.001) 5199 if (s < 0.001)
5141 { 5200 {
5142 x = 1; 5201 return new LSL_Vector(1, 0, 0);
5143 y = z = 0;
5144 } 5202 }
5145 else 5203 else
5146 { 5204 {
5147 x = rot.x / s; // normalise axis 5205 double invS = 1.0 / s;
5148 y = rot.y / s; 5206 if (rot.s < 0) invS = -invS;
5149 z = rot.z / s; 5207 return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS);
5150 } 5208 }
5151
5152 return new LSL_Vector(x,y,z);
5153 } 5209 }
5154 5210
5155 5211
@@ -5158,18 +5214,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5158 { 5214 {
5159 m_host.AddScriptLPS(1); 5215 m_host.AddScriptLPS(1);
5160 5216
5161 if (rot.s > 1) // normalization needed 5217 if (Math.Abs(rot.s) > 1) // normalization needed
5162 { 5218 rot.Normalize();
5163 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
5164 rot.z * rot.z + rot.s * rot.s);
5165
5166 rot.x /= length;
5167 rot.y /= length;
5168 rot.z /= length;
5169 rot.s /= length;
5170 }
5171 5219
5172 double angle = 2 * Math.Acos(rot.s); 5220 double angle = 2 * Math.Acos(rot.s);
5221 if (angle > Math.PI)
5222 angle = 2 * Math.PI - angle;
5173 5223
5174 return angle; 5224 return angle;
5175 } 5225 }
@@ -6687,7 +6737,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6687 PSYS_SRC_TARGET_KEY = 20, 6737 PSYS_SRC_TARGET_KEY = 20,
6688 PSYS_SRC_OMEGA = 21, 6738 PSYS_SRC_OMEGA = 21,
6689 PSYS_SRC_ANGLE_BEGIN = 22, 6739 PSYS_SRC_ANGLE_BEGIN = 22,
6690 PSYS_SRC_ANGLE_END = 23 6740 PSYS_SRC_ANGLE_END = 23,
6741 PSYS_PART_BLEND_FUNC_SOURCE = 24,
6742 PSYS_PART_BLEND_FUNC_DEST = 25,
6743 PSYS_PART_START_GLOW = 26,
6744 PSYS_PART_END_GLOW = 27
6691 } 6745 }
6692 6746
6693 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) 6747 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
@@ -6713,6 +6767,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6713 ps.BurstRate = 0.1f; 6767 ps.BurstRate = 0.1f;
6714 ps.PartMaxAge = 10.0f; 6768 ps.PartMaxAge = 10.0f;
6715 ps.BurstPartCount = 1; 6769 ps.BurstPartCount = 1;
6770 ps.BlendFuncSource = ScriptBaseClass.PSYS_PART_BF_SOURCE_ALPHA;
6771 ps.BlendFuncDest = ScriptBaseClass.PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA;
6772 ps.PartStartGlow = 0.0f;
6773 ps.PartEndGlow = 0.0f;
6774
6716 return ps; 6775 return ps;
6717 } 6776 }
6718 6777
@@ -6747,6 +6806,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6747 LSL_Vector tempv = new LSL_Vector(); 6806 LSL_Vector tempv = new LSL_Vector();
6748 6807
6749 float tempf = 0; 6808 float tempf = 0;
6809 int tmpi = 0;
6750 6810
6751 for (int i = 0; i < rules.Length; i += 2) 6811 for (int i = 0; i < rules.Length; i += 2)
6752 { 6812 {
@@ -6805,7 +6865,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6805 break; 6865 break;
6806 6866
6807 case (int)ScriptBaseClass.PSYS_SRC_PATTERN: 6867 case (int)ScriptBaseClass.PSYS_SRC_PATTERN:
6808 int tmpi = (int)rules.GetLSLIntegerItem(i + 1); 6868 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6809 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; 6869 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
6810 break; 6870 break;
6811 6871
@@ -6825,6 +6885,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6825 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. 6885 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
6826 break; 6886 break;
6827 6887
6888 case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE:
6889 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6890 prules.BlendFuncSource = (byte)tmpi;
6891 break;
6892
6893 case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST:
6894 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6895 prules.BlendFuncDest = (byte)tmpi;
6896 break;
6897
6898 case (int)ScriptBaseClass.PSYS_PART_START_GLOW:
6899 tempf = (float)rules.GetLSLFloatItem(i + 1);
6900 prules.PartStartGlow = (float)tempf;
6901 break;
6902
6903 case (int)ScriptBaseClass.PSYS_PART_END_GLOW:
6904 tempf = (float)rules.GetLSLFloatItem(i + 1);
6905 prules.PartEndGlow = (float)tempf;
6906 break;
6907
6828 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: 6908 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
6829 prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1)); 6909 prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1));
6830 break; 6910 break;
@@ -8255,7 +8335,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8255 return null; 8335 return null;
8256 8336
8257 string ph = rules.Data[idx++].ToString(); 8337 string ph = rules.Data[idx++].ToString();
8258 parentgrp.ScriptSetPhantomStatus(ph.Equals("1")); 8338 part.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1"));
8259 8339
8260 break; 8340 break;
8261 8341
@@ -8308,7 +8388,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8308 return null; 8388 return null;
8309 string temp = rules.Data[idx++].ToString(); 8389 string temp = rules.Data[idx++].ToString();
8310 8390
8311 parentgrp.ScriptSetTemporaryStatus(temp.Equals("1")); 8391 part.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1"));
8312 8392
8313 break; 8393 break;
8314 8394
@@ -8846,8 +8926,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8846 int idx=0; 8926 int idx=0;
8847 while (idx < rules.Length) 8927 while (idx < rules.Length)
8848 { 8928 {
8849 int code=(int)rules.GetLSLIntegerItem(idx++); 8929 int code = (int)rules.GetLSLIntegerItem(idx++);
8850 int remain=rules.Length-idx; 8930 int remain = rules.Length - idx;
8851 8931
8852 switch (code) 8932 switch (code)
8853 { 8933 {
@@ -8920,7 +9000,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8920 break; 9000 break;
8921 9001
8922 case ScriptBaseClass.PRIM_TYPE_SCULPT: 9002 case ScriptBaseClass.PRIM_TYPE_SCULPT:
8923 res.Add(Shape.SculptTexture.ToString()); 9003 res.Add(new LSL_String(Shape.SculptTexture.ToString()));
8924 res.Add(new LSL_Integer(Shape.SculptType)); 9004 res.Add(new LSL_Integer(Shape.SculptType));
8925 break; 9005 break;
8926 9006
@@ -9262,7 +9342,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9262 )); 9342 ));
9263 break; 9343 break;
9264 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 9344 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9265 if(remain < 3) 9345
9346 // TODO: Should be issuing a runtime script warning in this case.
9347 if (remain < 2)
9266 return null; 9348 return null;
9267 9349
9268 return rules.GetSublist(idx, -1); 9350 return rules.GetSublist(idx, -1);
@@ -12673,6 +12755,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12673 public void llSetSoundQueueing(int queue) 12755 public void llSetSoundQueueing(int queue)
12674 { 12756 {
12675 m_host.AddScriptLPS(1); 12757 m_host.AddScriptLPS(1);
12758
12759 if (m_SoundModule != null)
12760 m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value);
12676 } 12761 }
12677 12762
12678 public void llCollisionSprite(string impact_sprite) 12763 public void llCollisionSprite(string impact_sprite)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index 1d6cb6d..b13a5ae 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -434,6 +434,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
434 } 434 }
435 return wl; 435 return wl;
436 } 436 }
437
437 /// <summary> 438 /// <summary>
438 /// Set the current Windlight scene 439 /// Set the current Windlight scene
439 /// </summary> 440 /// </summary>
@@ -446,13 +447,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
446 LSShoutError("LightShare functions are not enabled."); 447 LSShoutError("LightShare functions are not enabled.");
447 return 0; 448 return 0;
448 } 449 }
449 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 450
451 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
450 { 452 {
451 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); 453 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
452 return 0; 454
455 if (sp == null || sp.GodLevel < 200)
456 {
457 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
458 return 0;
459 }
453 } 460 }
461
454 int success = 0; 462 int success = 0;
455 m_host.AddScriptLPS(1); 463 m_host.AddScriptLPS(1);
464
456 if (LightShareModule.EnableWindlight) 465 if (LightShareModule.EnableWindlight)
457 { 466 {
458 RegionLightShareData wl = getWindlightProfileFromRules(rules); 467 RegionLightShareData wl = getWindlightProfileFromRules(rules);
@@ -465,8 +474,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
465 LSShoutError("Windlight module is disabled"); 474 LSShoutError("Windlight module is disabled");
466 return 0; 475 return 0;
467 } 476 }
477
468 return success; 478 return success;
469 } 479 }
480
470 public void lsClearWindlightScene() 481 public void lsClearWindlightScene()
471 { 482 {
472 if (!m_LSFunctionsEnabled) 483 if (!m_LSFunctionsEnabled)
@@ -474,17 +485,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
474 LSShoutError("LightShare functions are not enabled."); 485 LSShoutError("LightShare functions are not enabled.");
475 return; 486 return;
476 } 487 }
477 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 488
489 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
478 { 490 {
479 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); 491 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
480 return; 492
493 if (sp == null || sp.GodLevel < 200)
494 {
495 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
496 return;
497 }
481 } 498 }
482 499
483 m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.valid = false; 500 m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.valid = false;
484 if (m_host.ParentGroup.Scene.SimulationDataService != null) 501 if (m_host.ParentGroup.Scene.SimulationDataService != null)
485 m_host.ParentGroup.Scene.SimulationDataService.RemoveRegionWindlightSettings(m_host.ParentGroup.Scene.RegionInfo.RegionID); 502 m_host.ParentGroup.Scene.SimulationDataService.RemoveRegionWindlightSettings(m_host.ParentGroup.Scene.RegionInfo.RegionID);
503
486 m_host.ParentGroup.Scene.EventManager.TriggerOnSaveNewWindlightProfile(); 504 m_host.ParentGroup.Scene.EventManager.TriggerOnSaveNewWindlightProfile();
487 } 505 }
506
488 /// <summary> 507 /// <summary>
489 /// Set the current Windlight scene to a target avatar 508 /// Set the current Windlight scene to a target avatar
490 /// </summary> 509 /// </summary>
@@ -497,13 +516,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
497 LSShoutError("LightShare functions are not enabled."); 516 LSShoutError("LightShare functions are not enabled.");
498 return 0; 517 return 0;
499 } 518 }
500 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 519
520 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
501 { 521 {
502 LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); 522 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
503 return 0; 523
524 if (sp == null || sp.GodLevel < 200)
525 {
526 LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners.");
527 return 0;
528 }
504 } 529 }
530
505 int success = 0; 531 int success = 0;
506 m_host.AddScriptLPS(1); 532 m_host.AddScriptLPS(1);
533
507 if (LightShareModule.EnableWindlight) 534 if (LightShareModule.EnableWindlight)
508 { 535 {
509 RegionLightShareData wl = getWindlightProfileFromRules(rules); 536 RegionLightShareData wl = getWindlightProfileFromRules(rules);
@@ -515,8 +542,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
515 LSShoutError("Windlight module is disabled"); 542 LSShoutError("Windlight module is disabled");
516 return 0; 543 return 0;
517 } 544 }
545
518 return success; 546 return success;
519 } 547 }
520
521 } 548 }
522} 549} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index bd776b6..edcdfbc 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -319,7 +319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
319 319
320 object[] convertedParms = new object[parms.Length]; 320 object[] convertedParms = new object[parms.Length];
321 for (int i = 0; i < parms.Length; i++) 321 for (int i = 0; i < parms.Length; i++)
322 convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname); 322 convertedParms[i] = ConvertFromLSL(parms[i], signature[i], fname);
323 323
324 // now call the function, the contract with the function is that it will always return 324 // now call the function, the contract with the function is that it will always return
325 // non-null but don't trust it completely 325 // non-null but don't trust it completely
@@ -448,7 +448,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
448 } 448 }
449 } 449 }
450 450
451 MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname)); 451 MODError(String.Format("{0}: parameter type mismatch; expecting {1}, type(parm)={2}", fname, type.Name, lslparm.GetType()));
452 return null; 452 return null;
453 } 453 }
454 454
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 9c148d1..7081416 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -3005,6 +3005,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3005 return ret; 3005 return ret;
3006 } 3006 }
3007 3007
3008 public LSL_Vector osGetRegionSize()
3009 {
3010 CheckThreatLevel(ThreatLevel.None, "osGetRegionSize");
3011 m_host.AddScriptLPS(1);
3012
3013 bool isMegaregion;
3014 IRegionCombinerModule rcMod = World.RequestModuleInterface<IRegionCombinerModule>();
3015 if (rcMod != null)
3016 isMegaregion = rcMod.IsRootForMegaregion(World.RegionInfo.RegionID);
3017 else
3018 isMegaregion = false;
3019
3020 if (isMegaregion)
3021 {
3022 Vector2 size = rcMod.GetSizeOfMegaregion(World.RegionInfo.RegionID);
3023 return new LSL_Vector(size.X, size.Y, Constants.RegionHeight);
3024 }
3025 else
3026 {
3027 return new LSL_Vector((float)Constants.RegionSize, (float)Constants.RegionSize, Constants.RegionHeight);
3028 }
3029 }
3030
3008 public int osGetSimulatorMemory() 3031 public int osGetSimulatorMemory()
3009 { 3032 {
3010 CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory"); 3033 CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory");
@@ -3043,7 +3066,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3043 sp.ControllingClient.Kick(alert); 3066 sp.ControllingClient.Kick(alert);
3044 3067
3045 // ...and close on our side 3068 // ...and close on our side
3046 sp.Scene.IncomingCloseAgent(sp.UUID, false); 3069 sp.Scene.CloseAgent(sp.UUID, false);
3047 } 3070 }
3048 }); 3071 });
3049 } 3072 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index a47e452..181399d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -353,6 +353,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
353 // Position of a sensor in a child prim attached to an avatar 353 // Position of a sensor in a child prim attached to an avatar
354 // will be still wrong. 354 // will be still wrong.
355 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 355 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
356
357 // Don't proceed if the avatar for this attachment has since been removed from the scene.
358 if (avatar == null)
359 return sensedEntities;
360
356 fromRegionPos = avatar.AbsolutePosition; 361 fromRegionPos = avatar.AbsolutePosition;
357 q = avatar.Rotation; 362 q = avatar.Rotation;
358 } 363 }
@@ -363,7 +368,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
363 368
364 Vector3 ZeroVector = new Vector3(0, 0, 0); 369 Vector3 ZeroVector = new Vector3(0, 0, 0);
365 370
366 bool nameSearch = (ts.name != null && ts.name != ""); 371 bool nameSearch = !string.IsNullOrEmpty(ts.name);
367 372
368 foreach (EntityBase ent in Entities) 373 foreach (EntityBase ent in Entities)
369 { 374 {
@@ -483,6 +488,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
483 // Position of a sensor in a child prim attached to an avatar 488 // Position of a sensor in a child prim attached to an avatar
484 // will be still wrong. 489 // will be still wrong.
485 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 490 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
491
492 // Don't proceed if the avatar for this attachment has since been removed from the scene.
486 if (avatar == null) 493 if (avatar == null)
487 return sensedEntities; 494 return sensedEntities;
488 fromRegionPos = avatar.AbsolutePosition; 495 fromRegionPos = avatar.AbsolutePosition;
@@ -601,7 +608,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
601 return sensedEntities; 608 return sensedEntities;
602 senseEntity(sp); 609 senseEntity(sp);
603 } 610 }
604 else if (ts.name != null && ts.name != "") 611 else if (!string.IsNullOrEmpty(ts.name))
605 { 612 {
606 ScenePresence sp; 613 ScenePresence sp;
607 // Try lookup by name will return if/when found 614 // Try lookup by name will return if/when found
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
index 6d218a6..9137c69 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index daf89e5..d211a2b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -332,7 +332,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
332 void llSensorRemove(); 332 void llSensorRemove();
333 void llSensorRepeat(string name, string id, int type, double range, double arc, double rate); 333 void llSensorRepeat(string name, string id, int type, double range, double arc, double rate);
334 void llSetAlpha(double alpha, int face); 334 void llSetAlpha(double alpha, int face);
335 void llSetAngularVelocity(LSL_Vector angvelocity, int local);
336 void llSetBuoyancy(double buoyancy); 335 void llSetBuoyancy(double buoyancy);
337 void llSetCameraAtOffset(LSL_Vector offset); 336 void llSetCameraAtOffset(LSL_Vector offset);
338 void llSetCameraEyeOffset(LSL_Vector offset); 337 void llSetCameraEyeOffset(LSL_Vector offset);
@@ -340,9 +339,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
340 void llSetCameraParams(LSL_List rules); 339 void llSetCameraParams(LSL_List rules);
341 void llSetClickAction(int action); 340 void llSetClickAction(int action);
342 void llSetColor(LSL_Vector color, int face); 341 void llSetColor(LSL_Vector color, int face);
342 void llSetContentType(LSL_Key id, LSL_Integer type);
343 void llSetDamage(double damage); 343 void llSetDamage(double damage);
344 void llSetForce(LSL_Vector force, int local); 344 void llSetForce(LSL_Vector force, int local);
345 void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local); 345 void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local);
346 void llSetAngularVelocity(LSL_Vector angularVelocity, int local);
346 void llSetHoverHeight(double height, int water, double tau); 347 void llSetHoverHeight(double height, int water, double tau);
347 void llSetInventoryPermMask(string item, int mask, int value); 348 void llSetInventoryPermMask(string item, int mask, int value);
348 void llSetLinkAlpha(int linknumber, double alpha, int face); 349 void llSetLinkAlpha(int linknumber, double alpha, int face);
@@ -383,7 +384,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
383 void llSetVehicleRotationParam(int param, LSL_Rotation rot); 384 void llSetVehicleRotationParam(int param, LSL_Rotation rot);
384 void llSetVehicleType(int type); 385 void llSetVehicleType(int type);
385 void llSetVehicleVectorParam(int param, LSL_Vector vec); 386 void llSetVehicleVectorParam(int param, LSL_Vector vec);
386 void llSetVelocity(LSL_Vector velocity, int local);
387 void llShout(int channelID, string text); 387 void llShout(int channelID, string text);
388 LSL_Float llSin(double f); 388 LSL_Float llSin(double f);
389 void llSitTarget(LSL_Vector offset, LSL_Rotation rot); 389 void llSitTarget(LSL_Vector offset, LSL_Rotation rot);
@@ -434,6 +434,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
434 void llSetKeyframedMotion(LSL_List frames, LSL_List options); 434 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
435 LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 435 LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
436 LSL_List llGetPhysicsMaterial(); 436 LSL_List llGetPhysicsMaterial();
437 void llSetContentType(LSL_Key id, LSL_Integer content_type);
438 } 437 }
439} 438}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index a652cb8..d80d389 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -336,6 +336,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
336 key osGetMapTexture(); 336 key osGetMapTexture();
337 key osGetRegionMapTexture(string regionName); 337 key osGetRegionMapTexture(string regionName);
338 LSL_List osGetRegionStats(); 338 LSL_List osGetRegionStats();
339 vector osGetRegionSize();
339 340
340 int osGetSimulatorMemory(); 341 int osGetSimulatorMemory();
341 void osKickAvatar(string FirstName,string SurName,string alert); 342 void osKickAvatar(string FirstName,string SurName,string alert);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 6efa73f..e59c0be 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -107,6 +107,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
107 public const int PSYS_PART_TARGET_POS_MASK = 64; 107 public const int PSYS_PART_TARGET_POS_MASK = 64;
108 public const int PSYS_PART_TARGET_LINEAR_MASK = 128; 108 public const int PSYS_PART_TARGET_LINEAR_MASK = 128;
109 public const int PSYS_PART_EMISSIVE_MASK = 256; 109 public const int PSYS_PART_EMISSIVE_MASK = 256;
110 public const int PSYS_PART_RIBBON_MASK = 1024;
110 public const int PSYS_PART_FLAGS = 0; 111 public const int PSYS_PART_FLAGS = 0;
111 public const int PSYS_PART_START_COLOR = 1; 112 public const int PSYS_PART_START_COLOR = 1;
112 public const int PSYS_PART_START_ALPHA = 2; 113 public const int PSYS_PART_START_ALPHA = 2;
@@ -130,6 +131,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
130 public const int PSYS_SRC_OMEGA = 21; 131 public const int PSYS_SRC_OMEGA = 21;
131 public const int PSYS_SRC_ANGLE_BEGIN = 22; 132 public const int PSYS_SRC_ANGLE_BEGIN = 22;
132 public const int PSYS_SRC_ANGLE_END = 23; 133 public const int PSYS_SRC_ANGLE_END = 23;
134 public const int PSYS_PART_BLEND_FUNC_SOURCE = 24;
135 public const int PSYS_PART_BLEND_FUNC_DEST = 25;
136 public const int PSYS_PART_START_GLOW = 26;
137 public const int PSYS_PART_END_GLOW = 27;
138 public const int PSYS_PART_BF_ONE = 0;
139 public const int PSYS_PART_BF_ZERO = 1;
140 public const int PSYS_PART_BF_DEST_COLOR = 2;
141 public const int PSYS_PART_BF_SOURCE_COLOR = 3;
142 public const int PSYS_PART_BF_ONE_MINUS_DEST_COLOR = 4;
143 public const int PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR = 5;
144 public const int PSYS_PART_BF_SOURCE_ALPHA = 7;
145 public const int PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA = 9;
133 public const int PSYS_SRC_PATTERN_DROP = 1; 146 public const int PSYS_SRC_PATTERN_DROP = 1;
134 public const int PSYS_SRC_PATTERN_EXPLODE = 2; 147 public const int PSYS_SRC_PATTERN_EXPLODE = 2;
135 public const int PSYS_SRC_PATTERN_ANGLE = 4; 148 public const int PSYS_SRC_PATTERN_ANGLE = 4;
@@ -361,6 +374,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
361 public const int HTTP_CUSTOM_HEADER = 5; 374 public const int HTTP_CUSTOM_HEADER = 5;
362 public const int HTTP_PRAGMA_NO_CACHE = 6; 375 public const int HTTP_PRAGMA_NO_CACHE = 6;
363 376
377 // llSetContentType
378 public const int CONTENT_TYPE_TEXT = 0; //text/plain
379 public const int CONTENT_TYPE_HTML = 1; //text/html
380 public const int CONTENT_TYPE_XML = 2; //application/xml
381 public const int CONTENT_TYPE_XHTML = 3; //application/xhtml+xml
382 public const int CONTENT_TYPE_ATOM = 4; //application/atom+xml
383 public const int CONTENT_TYPE_JSON = 5; //application/json
384 public const int CONTENT_TYPE_LLSD = 6; //application/llsd+xml
385 public const int CONTENT_TYPE_FORM = 7; //application/x-www-form-urlencoded
386 public const int CONTENT_TYPE_RSS = 8; //application/rss+xml
387
364 public const int PRIM_MATERIAL = 2; 388 public const int PRIM_MATERIAL = 2;
365 public const int PRIM_PHYSICS = 3; 389 public const int PRIM_PHYSICS = 3;
366 public const int PRIM_TEMP_ON_REZ = 4; 390 public const int PRIM_TEMP_ON_REZ = 4;
@@ -772,8 +796,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
772 /// process message parameter as regex 796 /// process message parameter as regex
773 /// </summary> 797 /// </summary>
774 public const int OS_LISTEN_REGEX_MESSAGE = 0x2; 798 public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
775
776 public const int CONTENT_TYPE_TEXT = 0;
777 public const int CONTENT_TYPE_HTML = 1;
778 } 799 }
779} 800}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 6f3677c..4fc8d65 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -1495,11 +1495,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1495 m_LSL_Functions.llSetAlpha(alpha, face); 1495 m_LSL_Functions.llSetAlpha(alpha, face);
1496 } 1496 }
1497 1497
1498 public void llSetAngularVelocity(LSL_Vector angvelocity, int local)
1499 {
1500 m_LSL_Functions.llSetAngularVelocity(angvelocity, local);
1501 }
1502
1503 public void llSetBuoyancy(double buoyancy) 1498 public void llSetBuoyancy(double buoyancy)
1504 { 1499 {
1505 m_LSL_Functions.llSetBuoyancy(buoyancy); 1500 m_LSL_Functions.llSetBuoyancy(buoyancy);
@@ -1535,6 +1530,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1535 m_LSL_Functions.llSetColor(color, face); 1530 m_LSL_Functions.llSetColor(color, face);
1536 } 1531 }
1537 1532
1533 public void llSetContentType(LSL_Key id, LSL_Integer type)
1534 {
1535 m_LSL_Functions.llSetContentType(id, type);
1536 }
1537
1538 public void llSetDamage(double damage) 1538 public void llSetDamage(double damage)
1539 { 1539 {
1540 m_LSL_Functions.llSetDamage(damage); 1540 m_LSL_Functions.llSetDamage(damage);
@@ -1550,6 +1550,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1550 m_LSL_Functions.llSetForceAndTorque(force, torque, local); 1550 m_LSL_Functions.llSetForceAndTorque(force, torque, local);
1551 } 1551 }
1552 1552
1553 public void llSetAngularVelocity(LSL_Vector force, int local)
1554 {
1555 m_LSL_Functions.llSetAngularVelocity(force, local);
1556 }
1557
1553 public void llSetHoverHeight(double height, int water, double tau) 1558 public void llSetHoverHeight(double height, int water, double tau)
1554 { 1559 {
1555 m_LSL_Functions.llSetHoverHeight(height, water, tau); 1560 m_LSL_Functions.llSetHoverHeight(height, water, tau);
@@ -1740,11 +1745,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1740 m_LSL_Functions.llSetVehicleVectorParam(param, vec); 1745 m_LSL_Functions.llSetVehicleVectorParam(param, vec);
1741 } 1746 }
1742 1747
1743 public void llSetVelocity(LSL_Vector velocity, int local)
1744 {
1745 m_LSL_Functions.llSetVelocity(velocity, local);
1746 }
1747
1748 public void llShout(int channelID, string text) 1748 public void llShout(int channelID, string text)
1749 { 1749 {
1750 m_LSL_Functions.llShout(channelID, text); 1750 m_LSL_Functions.llShout(channelID, text);
@@ -2014,10 +2014,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
2014 { 2014 {
2015 return m_LSL_Functions.llGetPhysicsMaterial(); 2015 return m_LSL_Functions.llGetPhysicsMaterial();
2016 } 2016 }
2017
2018 public void llSetContentType(LSL_Key id, LSL_Integer content_type)
2019 {
2020 m_LSL_Functions.llSetContentType(id, content_type);
2021 }
2022 } 2017 }
2023} 2018}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index b63773b..9cf7b35 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -858,6 +858,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
858 return m_OSSL_Functions.osGetRegionStats(); 858 return m_OSSL_Functions.osGetRegionStats();
859 } 859 }
860 860
861 public vector osGetRegionSize()
862 {
863 return m_OSSL_Functions.osGetRegionSize();
864 }
865
861 /// <summary> 866 /// <summary>
862 /// Returns the amount of memory in use by the Simulator Daemon. 867 /// Returns the amount of memory in use by the Simulator Daemon.
863 /// Amount in bytes - if >= 4GB, returns 4GB. (LSL is not 64-bit aware) 868 /// Amount in bytes - if >= 4GB, returns 4GB. (LSL is not 64-bit aware)
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
index 9e32f40..6aa717d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -937,7 +937,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
937 { 937 {
938 string retval = null; 938 string retval = null;
939 if (value is int) 939 if (value is int)
940 retval = ((int)value).ToString(); 940 retval = String.Format("new LSL_Types.LSLInteger({0})",((int)value).ToString());
941 else if (value is float) 941 else if (value is float)
942 retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString()); 942 retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString());
943 else if (value is string) 943 else if (value is string)
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index b71afe3..a1b8d85 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -610,6 +610,7 @@ namespace SecondLife
610 results = CScodeProvider.CompileAssemblyFromSource( 610 results = CScodeProvider.CompileAssemblyFromSource(
611 parameters, Script); 611 parameters, Script);
612 } 612 }
613
613 // Deal with an occasional segv in the compiler. 614 // Deal with an occasional segv in the compiler.
614 // Rarely, if ever, occurs twice in succession. 615 // Rarely, if ever, occurs twice in succession.
615 // Line # == 0 and no file name are indications that 616 // Line # == 0 and no file name are indications that
@@ -617,7 +618,7 @@ namespace SecondLife
617 // error log. 618 // error log.
618 if (results.Errors.Count > 0) 619 if (results.Errors.Count > 0)
619 { 620 {
620 if (!retried && (results.Errors[0].FileName == null || results.Errors[0].FileName == String.Empty) && 621 if (!retried && string.IsNullOrEmpty(results.Errors[0].FileName) &&
621 results.Errors[0].Line == 0) 622 results.Errors[0].Line == 0)
622 { 623 {
623 // System.Console.WriteLine("retrying failed compilation"); 624 // System.Console.WriteLine("retrying failed compilation");
@@ -647,15 +648,19 @@ namespace SecondLife
647 "language type \"" + lang.ToString() + "\""); 648 "language type \"" + lang.ToString() + "\"");
648 } 649 }
649 650
650 // Check result 651// foreach (Type type in results.CompiledAssembly.GetTypes())
651 // Go through errors 652// {
653// foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
654// {
655// m_log.DebugFormat("[COMPILER]: {0}.{1}", type.FullName, method.Name);
656// }
657// }
652 658
653 // 659 //
654 // WARNINGS AND ERRORS 660 // WARNINGS AND ERRORS
655 // 661 //
656 bool hadErrors = false; 662 bool hadErrors = false;
657 string errtext = String.Empty; 663 string errtext = String.Empty;
658
659 if (results.Errors.Count > 0) 664 if (results.Errors.Count > 0)
660 { 665 {
661 foreach (CompilerError CompErr in results.Errors) 666 foreach (CompilerError CompErr in results.Errors)
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSCodeTransformer.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSCodeTransformer.cs
index e77b3d2..0fb3574 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSCodeTransformer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSCodeTransformer.cs
@@ -27,12 +27,16 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
30using Tools; 32using Tools;
31 33
32namespace OpenSim.Region.ScriptEngine.Shared.CodeTools 34namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
33{ 35{
34 public class LSL2CSCodeTransformer 36 public class LSL2CSCodeTransformer
35 { 37 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
36 private SYMBOL m_astRoot = null; 40 private SYMBOL m_astRoot = null;
37 private static Dictionary<string, string> m_datatypeLSL2OpenSim = null; 41 private static Dictionary<string, string> m_datatypeLSL2OpenSim = null;
38 42
@@ -78,6 +82,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
78 /// <param name="s">The current node to transform.</param> 82 /// <param name="s">The current node to transform.</param>
79 private void TransformNode(SYMBOL s) 83 private void TransformNode(SYMBOL s)
80 { 84 {
85// m_log.DebugFormat("[LSL2CSCODETRANSFORMER]: Tranforming node {0}", s);
86
81 // make sure to put type lower in the inheritance hierarchy first 87 // make sure to put type lower in the inheritance hierarchy first
82 // ie: since IdentConstant and StringConstant inherit from Constant, 88 // ie: since IdentConstant and StringConstant inherit from Constant,
83 // put IdentConstant and StringConstant before Constant 89 // put IdentConstant and StringConstant before Constant
@@ -103,10 +109,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
103 // We need to check for that here. 109 // We need to check for that here.
104 if (null != s.kids[i]) 110 if (null != s.kids[i])
105 { 111 {
112// m_log.Debug("[LSL2CSCODETRANSFORMER]: Moving down level");
113
106 if (!(s is Assignment || s is ArgumentDeclarationList) && s.kids[i] is Declaration) 114 if (!(s is Assignment || s is ArgumentDeclarationList) && s.kids[i] is Declaration)
107 AddImplicitInitialization(s, i); 115 AddImplicitInitialization(s, i);
108 116
109 TransformNode((SYMBOL) s.kids[i]); 117 TransformNode((SYMBOL) s.kids[i]);
118
119// m_log.Debug("[LSL2CSCODETRANSFORMER]: Moving up level");
110 } 120 }
111 } 121 }
112 } 122 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
index 5b5c4fd..d163438 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
index 77e087c..b92f3a3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
@@ -762,6 +762,7 @@ default
762 public void TestIfStatement() 762 public void TestIfStatement()
763 { 763 {
764 TestHelpers.InMethod(); 764 TestHelpers.InMethod();
765// TestHelpers.EnableLogging();
765 766
766 string input = @"// let's test if statements 767 string input = @"// let's test if statements
767 768
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/LSL_EventTests.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/LSL_EventTests.cs
new file mode 100644
index 0000000..67ce10a
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/LSL_EventTests.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
28using System;
29using System.Collections.Generic;
30using System.Text.RegularExpressions;
31using NUnit.Framework;
32using OpenSim.Region.ScriptEngine.Shared.CodeTools;
33using OpenSim.Tests.Common;
34
35namespace OpenSim.Region.ScriptEngine.Shared.Tests
36{
37 public class LSL_EventTests : OpenSimTestCase
38 {
39 CSCodeGenerator m_cg = new CSCodeGenerator();
40
41 [Test]
42 public void TestBadEvent()
43 {
44 TestHelpers.InMethod();
45// TestHelpers.EnableLogging();
46
47 TestCompile("default { bad() {} }", true);
48 }
49
50 [Test]
51 public void TestAttachEvent()
52 {
53 TestHelpers.InMethod();
54// TestHelpers.EnableLogging();
55
56 TestKeyArgEvent("attach");
57 }
58
59 [Test]
60 public void TestObjectRezEvent()
61 {
62 TestHelpers.InMethod();
63// TestHelpers.EnableLogging();
64
65 TestKeyArgEvent("object_rez");
66 }
67
68 [Test]
69 public void TestMovingEndEvent()
70 {
71 TestHelpers.InMethod();
72// TestHelpers.EnableLogging();
73
74 TestVoidArgEvent("moving_end");
75 }
76
77 [Test]
78 public void TestMovingStartEvent()
79 {
80 TestHelpers.InMethod();
81// TestHelpers.EnableLogging();
82
83 TestVoidArgEvent("moving_start");
84 }
85
86 [Test]
87 public void TestNoSensorEvent()
88 {
89 TestHelpers.InMethod();
90// TestHelpers.EnableLogging();
91
92 TestVoidArgEvent("no_sensor");
93 }
94
95 [Test]
96 public void TestNotAtRotTargetEvent()
97 {
98 TestHelpers.InMethod();
99// TestHelpers.EnableLogging();
100
101 TestVoidArgEvent("not_at_rot_target");
102 }
103
104 [Test]
105 public void TestNotAtTargetEvent()
106 {
107 TestHelpers.InMethod();
108// TestHelpers.EnableLogging();
109
110 TestVoidArgEvent("not_at_target");
111 }
112
113 [Test]
114 public void TestStateEntryEvent()
115 {
116 TestHelpers.InMethod();
117// TestHelpers.EnableLogging();
118
119 TestVoidArgEvent("state_entry");
120 }
121
122 [Test]
123 public void TestStateExitEvent()
124 {
125 TestHelpers.InMethod();
126// TestHelpers.EnableLogging();
127
128 TestVoidArgEvent("state_exit");
129 }
130
131 [Test]
132 public void TestTimerEvent()
133 {
134 TestHelpers.InMethod();
135// TestHelpers.EnableLogging();
136
137 TestVoidArgEvent("timer");
138 }
139
140 private void TestVoidArgEvent(string eventName)
141 {
142 TestCompile("default { " + eventName + "() {} }", false);
143 TestCompile("default { " + eventName + "(integer n) {} }", true);
144 }
145
146 [Test]
147 public void TestChangedEvent()
148 {
149 TestHelpers.InMethod();
150// TestHelpers.EnableLogging();
151
152 TestIntArgEvent("changed");
153 }
154
155 [Test]
156 public void TestCollisionEvent()
157 {
158 TestHelpers.InMethod();
159// TestHelpers.EnableLogging();
160
161 TestIntArgEvent("collision");
162 }
163
164 [Test]
165 public void TestCollisionStartEvent()
166 {
167 TestHelpers.InMethod();
168// TestHelpers.EnableLogging();
169
170 TestIntArgEvent("collision_start");
171 }
172
173 [Test]
174 public void TestCollisionEndEvent()
175 {
176 TestHelpers.InMethod();
177// TestHelpers.EnableLogging();
178
179 TestIntArgEvent("collision_end");
180 }
181
182 [Test]
183 public void TestOnRezEvent()
184 {
185 TestHelpers.InMethod();
186// TestHelpers.EnableLogging();
187
188 TestIntArgEvent("on_rez");
189 }
190
191 [Test]
192 public void TestRunTimePermissionsEvent()
193 {
194 TestHelpers.InMethod();
195// TestHelpers.EnableLogging();
196
197 TestIntArgEvent("run_time_permissions");
198 }
199
200 [Test]
201 public void TestSensorEvent()
202 {
203 TestHelpers.InMethod();
204// TestHelpers.EnableLogging();
205
206 TestIntArgEvent("sensor");
207 }
208
209 [Test]
210 public void TestTouchEvent()
211 {
212 TestHelpers.InMethod();
213// TestHelpers.EnableLogging();
214
215 TestIntArgEvent("touch");
216 }
217
218 [Test]
219 public void TestTouchStartEvent()
220 {
221 TestHelpers.InMethod();
222// TestHelpers.EnableLogging();
223
224 TestIntArgEvent("touch_start");
225 }
226
227 [Test]
228 public void TestTouchEndEvent()
229 {
230 TestHelpers.InMethod();
231// TestHelpers.EnableLogging();
232
233 TestIntArgEvent("touch_end");
234 }
235
236 [Test]
237 public void TestLandCollisionEvent()
238 {
239 TestHelpers.InMethod();
240// TestHelpers.EnableLogging();
241
242 TestVectorArgEvent("land_collision");
243 }
244
245 [Test]
246 public void TestLandCollisionStartEvent()
247 {
248 TestHelpers.InMethod();
249// TestHelpers.EnableLogging();
250
251 TestVectorArgEvent("land_collision_start");
252 }
253
254 [Test]
255 public void TestLandCollisionEndEvent()
256 {
257 TestHelpers.InMethod();
258// TestHelpers.EnableLogging();
259
260 TestVectorArgEvent("land_collision_end");
261 }
262
263 [Test]
264 public void TestAtRotTargetEvent()
265 {
266 TestHelpers.InMethod();
267// TestHelpers.EnableLogging();
268
269 TestIntRotRotArgEvent("at_rot_target");
270 }
271
272 [Test]
273 public void TestAtTargetEvent()
274 {
275 TestHelpers.InMethod();
276// TestHelpers.EnableLogging();
277
278 TestIntVecVecArgEvent("at_target");
279 }
280
281 [Test]
282 public void TestControlEvent()
283 {
284 TestHelpers.InMethod();
285// TestHelpers.EnableLogging();
286
287 TestKeyIntIntArgEvent("control");
288 }
289
290 private void TestIntArgEvent(string eventName)
291 {
292 TestCompile("default { " + eventName + "(integer n) {} }", false);
293 TestCompile("default { " + eventName + "{{}} }", true);
294 TestCompile("default { " + eventName + "(string s) {{}} }", true);
295 TestCompile("default { " + eventName + "(integer n, integer o) {{}} }", true);
296 }
297
298 private void TestKeyArgEvent(string eventName)
299 {
300 TestCompile("default { " + eventName + "(key k) {} }", false);
301 TestCompile("default { " + eventName + "{{}} }", true);
302 TestCompile("default { " + eventName + "(string s) {{}} }", true);
303 TestCompile("default { " + eventName + "(key k, key l) {{}} }", true);
304 }
305
306 private void TestVectorArgEvent(string eventName)
307 {
308 TestCompile("default { " + eventName + "(vector v) {} }", false);
309 TestCompile("default { " + eventName + "{{}} }", true);
310 TestCompile("default { " + eventName + "(string s) {{}} }", true);
311 TestCompile("default { " + eventName + "(vector v, vector w) {{}} }", true);
312 }
313
314 private void TestIntRotRotArgEvent(string eventName)
315 {
316 TestCompile("default { " + eventName + "(integer n, rotation r, rotation s) {} }", false);
317 TestCompile("default { " + eventName + "{{}} }", true);
318 TestCompile("default { " + eventName + "(string s) {{}} }", true);
319 TestCompile("default { " + eventName + "(integer n, rotation r, rotation s, rotation t) {{}} }", true);
320 }
321
322 private void TestIntVecVecArgEvent(string eventName)
323 {
324 TestCompile("default { " + eventName + "(integer n, vector v, vector w) {} }", false);
325 TestCompile("default { " + eventName + "{{}} }", true);
326 TestCompile("default { " + eventName + "(string s) {{}} }", true);
327 TestCompile("default { " + eventName + "(integer n, vector v, vector w, vector x) {{}} }", true);
328 }
329
330 private void TestKeyIntIntArgEvent(string eventName)
331 {
332 TestCompile("default { " + eventName + "(key k, integer n, integer o) {} }", false);
333 TestCompile("default { " + eventName + "{{}} }", true);
334 TestCompile("default { " + eventName + "(string s) {{}} }", true);
335 TestCompile("default { " + eventName + "(key k, integer n, integer o, integer p) {{}} }", true);
336 }
337
338 private void TestCompile(string script, bool expectException)
339 {
340 bool gotException = false;
341 Exception ge = null;
342
343 try
344 {
345 m_cg.Convert(script);
346 }
347 catch (Exception e)
348 {
349 gotException = true;
350 ge = e;
351 }
352
353 Assert.That(
354 gotException,
355 Is.EqualTo(expectException),
356 "Failed on {0}, exception {1}", script, ge != null ? ge.ToString() : "n/a");
357 }
358 }
359} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/lsl.parser.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/lsl.parser.cs
index ca56cd6..44957bd 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/lsl.parser.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/lsl.parser.cs
@@ -116,9 +116,9 @@ public class StateEvent : SYMBOL{
116)yyp)){ m_name = name ; 116)yyp)){ m_name = name ;
117 kids . Add ( cs ); 117 kids . Add ( cs );
118} 118}
119 public StateEvent (Parser yyp, string name , ArgumentDeclarationList dal , CompoundStatement cs ):base(((LSLSyntax 119 public StateEvent (Parser yyp, string name , ArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
120)yyp)){ m_name = name ; 120)yyp)){ m_name = name ;
121 if (0< dal . kids . Count ) kids . Add ( dal ); 121 if (0< adl . kids . Count ) kids . Add ( adl );
122 kids . Add ( cs ); 122 kids . Add ( cs );
123} 123}
124 public override string ToString (){ return "EVENT<"+ m_name +">"; 124 public override string ToString (){ return "EVENT<"+ m_name +">";
@@ -130,20 +130,133 @@ public class StateEvent : SYMBOL{
130public override string yyname { get { return "StateEvent"; }} 130public override string yyname { get { return "StateEvent"; }}
131public override int yynum { get { return 103; }} 131public override int yynum { get { return 103; }}
132public StateEvent(Parser yyp):base(yyp){}} 132public StateEvent(Parser yyp):base(yyp){}}
133//%+ArgumentDeclarationList+104 133//%+VoidArgStateEvent+104
134public class VoidArgStateEvent : StateEvent{
135 public VoidArgStateEvent (Parser yyp, string name , CompoundStatement cs ):base(((LSLSyntax
136)yyp), name , cs ){}
137
138public override string yyname { get { return "VoidArgStateEvent"; }}
139public override int yynum { get { return 104; }}
140public VoidArgStateEvent(Parser yyp):base(yyp){}}
141//%+KeyArgStateEvent+105
142public class KeyArgStateEvent : StateEvent{
143 public KeyArgStateEvent (Parser yyp, string name , KeyArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
144)yyp), name , adl , cs ){}
145
146public override string yyname { get { return "KeyArgStateEvent"; }}
147public override int yynum { get { return 105; }}
148public KeyArgStateEvent(Parser yyp):base(yyp){}}
149//%+IntArgStateEvent+106
150public class IntArgStateEvent : StateEvent{
151 public IntArgStateEvent (Parser yyp, string name , IntArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
152)yyp), name , adl , cs ){}
153
154public override string yyname { get { return "IntArgStateEvent"; }}
155public override int yynum { get { return 106; }}
156public IntArgStateEvent(Parser yyp):base(yyp){}}
157//%+VectorArgStateEvent+107
158public class VectorArgStateEvent : StateEvent{
159 public VectorArgStateEvent (Parser yyp, string name , VectorArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
160)yyp), name , adl , cs ){}
161
162public override string yyname { get { return "VectorArgStateEvent"; }}
163public override int yynum { get { return 107; }}
164public VectorArgStateEvent(Parser yyp):base(yyp){}}
165//%+IntRotRotArgStateEvent+108
166public class IntRotRotArgStateEvent : StateEvent{
167 public IntRotRotArgStateEvent (Parser yyp, string name , IntRotRotArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
168)yyp), name , adl , cs ){}
169
170public override string yyname { get { return "IntRotRotArgStateEvent"; }}
171public override int yynum { get { return 108; }}
172public IntRotRotArgStateEvent(Parser yyp):base(yyp){}}
173//%+IntVecVecArgStateEvent+109
174public class IntVecVecArgStateEvent : StateEvent{
175 public IntVecVecArgStateEvent (Parser yyp, string name , IntVecVecArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
176)yyp), name , adl , cs ){}
177
178public override string yyname { get { return "IntVecVecArgStateEvent"; }}
179public override int yynum { get { return 109; }}
180public IntVecVecArgStateEvent(Parser yyp):base(yyp){}}
181//%+KeyIntIntArgStateEvent+110
182public class KeyIntIntArgStateEvent : StateEvent{
183 public KeyIntIntArgStateEvent (Parser yyp, string name , KeyIntIntArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
184)yyp), name , adl , cs ){}
185
186public override string yyname { get { return "KeyIntIntArgStateEvent"; }}
187public override int yynum { get { return 110; }}
188public KeyIntIntArgStateEvent(Parser yyp):base(yyp){}}
189//%+ArgumentDeclarationList+111
134public class ArgumentDeclarationList : SYMBOL{ 190public class ArgumentDeclarationList : SYMBOL{
135 public ArgumentDeclarationList (Parser yyp, Declaration d ):base(((LSLSyntax 191 public ArgumentDeclarationList (Parser yyp, Declaration d ):base(((LSLSyntax
136)yyp)){ kids . Add ( d ); 192)yyp)){ kids . Add ( d );
137} 193}
194 public ArgumentDeclarationList (Parser yyp, Declaration d , Declaration d2 ):base(((LSLSyntax
195)yyp)){ kids . Add ( d );
196 kids . Add ( d2 );
197}
198 public ArgumentDeclarationList (Parser yyp, Declaration d , Declaration d2 , Declaration d3 ):base(((LSLSyntax
199)yyp)){ kids . Add ( d );
200 kids . Add ( d2 );
201 kids . Add ( d3 );
202}
138 public ArgumentDeclarationList (Parser yyp, ArgumentDeclarationList adl , Declaration d ):base(((LSLSyntax 203 public ArgumentDeclarationList (Parser yyp, ArgumentDeclarationList adl , Declaration d ):base(((LSLSyntax
139)yyp)){ while (0< adl . kids . Count ) kids . Add ( adl . kids . Pop ()); 204)yyp)){ while (0< adl . kids . Count ) kids . Add ( adl . kids . Pop ());
140 kids . Add ( d ); 205 kids . Add ( d );
141} 206}
142 207
143public override string yyname { get { return "ArgumentDeclarationList"; }} 208public override string yyname { get { return "ArgumentDeclarationList"; }}
144public override int yynum { get { return 104; }} 209public override int yynum { get { return 111; }}
145public ArgumentDeclarationList(Parser yyp):base(yyp){}} 210public ArgumentDeclarationList(Parser yyp):base(yyp){}}
146//%+Declaration+105 211//%+KeyArgumentDeclarationList+112
212public class KeyArgumentDeclarationList : ArgumentDeclarationList{
213 public KeyArgumentDeclarationList (Parser yyp, KeyDeclaration d ):base(((LSLSyntax
214)yyp), d ){}
215
216public override string yyname { get { return "KeyArgumentDeclarationList"; }}
217public override int yynum { get { return 112; }}
218public KeyArgumentDeclarationList(Parser yyp):base(yyp){}}
219//%+IntArgumentDeclarationList+113
220public class IntArgumentDeclarationList : ArgumentDeclarationList{
221 public IntArgumentDeclarationList (Parser yyp, IntDeclaration d ):base(((LSLSyntax
222)yyp), d ){}
223
224public override string yyname { get { return "IntArgumentDeclarationList"; }}
225public override int yynum { get { return 113; }}
226public IntArgumentDeclarationList(Parser yyp):base(yyp){}}
227//%+VectorArgumentDeclarationList+114
228public class VectorArgumentDeclarationList : ArgumentDeclarationList{
229 public VectorArgumentDeclarationList (Parser yyp, VecDeclaration d ):base(((LSLSyntax
230)yyp), d ){}
231
232public override string yyname { get { return "VectorArgumentDeclarationList"; }}
233public override int yynum { get { return 114; }}
234public VectorArgumentDeclarationList(Parser yyp):base(yyp){}}
235//%+IntRotRotArgumentDeclarationList+115
236public class IntRotRotArgumentDeclarationList : ArgumentDeclarationList{
237 public IntRotRotArgumentDeclarationList (Parser yyp, Declaration d1 , Declaration d2 , Declaration d3 ):base(((LSLSyntax
238)yyp), d1 , d2 , d3 ){}
239
240public override string yyname { get { return "IntRotRotArgumentDeclarationList"; }}
241public override int yynum { get { return 115; }}
242public IntRotRotArgumentDeclarationList(Parser yyp):base(yyp){}}
243//%+IntVecVecArgumentDeclarationList+116
244public class IntVecVecArgumentDeclarationList : ArgumentDeclarationList{
245 public IntVecVecArgumentDeclarationList (Parser yyp, Declaration d1 , Declaration d2 , Declaration d3 ):base(((LSLSyntax
246)yyp), d1 , d2 , d3 ){}
247
248public override string yyname { get { return "IntVecVecArgumentDeclarationList"; }}
249public override int yynum { get { return 116; }}
250public IntVecVecArgumentDeclarationList(Parser yyp):base(yyp){}}
251//%+KeyIntIntArgumentDeclarationList+117
252public class KeyIntIntArgumentDeclarationList : ArgumentDeclarationList{
253 public KeyIntIntArgumentDeclarationList (Parser yyp, Declaration d1 , Declaration d2 , Declaration d3 ):base(((LSLSyntax
254)yyp), d1 , d2 , d3 ){}
255
256public override string yyname { get { return "KeyIntIntArgumentDeclarationList"; }}
257public override int yynum { get { return 117; }}
258public KeyIntIntArgumentDeclarationList(Parser yyp):base(yyp){}}
259//%+Declaration+118
147public class Declaration : SYMBOL{ 260public class Declaration : SYMBOL{
148 private string m_datatype ; 261 private string m_datatype ;
149 private string m_id ; 262 private string m_id ;
@@ -163,9 +276,41 @@ public class Declaration : SYMBOL{
163} 276}
164 277
165public override string yyname { get { return "Declaration"; }} 278public override string yyname { get { return "Declaration"; }}
166public override int yynum { get { return 105; }} 279public override int yynum { get { return 118; }}
167public Declaration(Parser yyp):base(yyp){}} 280public Declaration(Parser yyp):base(yyp){}}
168//%+Typename+106 281//%+KeyDeclaration+119
282public class KeyDeclaration : Declaration{
283 public KeyDeclaration (Parser yyp, string type , string id ):base(((LSLSyntax
284)yyp), type , id ){}
285
286public override string yyname { get { return "KeyDeclaration"; }}
287public override int yynum { get { return 119; }}
288public KeyDeclaration(Parser yyp):base(yyp){}}
289//%+IntDeclaration+120
290public class IntDeclaration : Declaration{
291 public IntDeclaration (Parser yyp, string type , string id ):base(((LSLSyntax
292)yyp), type , id ){}
293
294public override string yyname { get { return "IntDeclaration"; }}
295public override int yynum { get { return 120; }}
296public IntDeclaration(Parser yyp):base(yyp){}}
297//%+VecDeclaration+121
298public class VecDeclaration : Declaration{
299 public VecDeclaration (Parser yyp, string type , string id ):base(((LSLSyntax
300)yyp), type , id ){}
301
302public override string yyname { get { return "VecDeclaration"; }}
303public override int yynum { get { return 121; }}
304public VecDeclaration(Parser yyp):base(yyp){}}
305//%+RotDeclaration+122
306public class RotDeclaration : Declaration{
307 public RotDeclaration (Parser yyp, string type , string id ):base(((LSLSyntax
308)yyp), type , id ){}
309
310public override string yyname { get { return "RotDeclaration"; }}
311public override int yynum { get { return 122; }}
312public RotDeclaration(Parser yyp):base(yyp){}}
313//%+Typename+123
169public class Typename : SYMBOL{ 314public class Typename : SYMBOL{
170 public string yytext ; 315 public string yytext ;
171 public Typename (Parser yyp, string text ):base(((LSLSyntax 316 public Typename (Parser yyp, string text ):base(((LSLSyntax
@@ -173,9 +318,9 @@ public class Typename : SYMBOL{
173} 318}
174 319
175public override string yyname { get { return "Typename"; }} 320public override string yyname { get { return "Typename"; }}
176public override int yynum { get { return 106; }} 321public override int yynum { get { return 123; }}
177public Typename(Parser yyp):base(yyp){}} 322public Typename(Parser yyp):base(yyp){}}
178//%+Event+107 323//%+Event+124
179public class Event : SYMBOL{ 324public class Event : SYMBOL{
180 public string yytext ; 325 public string yytext ;
181 public Event (Parser yyp, string text ):base(((LSLSyntax 326 public Event (Parser yyp, string text ):base(((LSLSyntax
@@ -183,9 +328,65 @@ public class Event : SYMBOL{
183} 328}
184 329
185public override string yyname { get { return "Event"; }} 330public override string yyname { get { return "Event"; }}
186public override int yynum { get { return 107; }} 331public override int yynum { get { return 124; }}
187public Event(Parser yyp):base(yyp){}} 332public Event(Parser yyp):base(yyp){}}
188//%+CompoundStatement+108 333//%+VoidArgEvent+125
334public class VoidArgEvent : Event{
335 public VoidArgEvent (Parser yyp, string text ):base(((LSLSyntax
336)yyp), text ){}
337
338public override string yyname { get { return "VoidArgEvent"; }}
339public override int yynum { get { return 125; }}
340public VoidArgEvent(Parser yyp):base(yyp){}}
341//%+KeyArgEvent+126
342public class KeyArgEvent : Event{
343 public KeyArgEvent (Parser yyp, string text ):base(((LSLSyntax
344)yyp), text ){}
345
346public override string yyname { get { return "KeyArgEvent"; }}
347public override int yynum { get { return 126; }}
348public KeyArgEvent(Parser yyp):base(yyp){}}
349//%+IntArgEvent+127
350public class IntArgEvent : Event{
351 public IntArgEvent (Parser yyp, string text ):base(((LSLSyntax
352)yyp), text ){}
353
354public override string yyname { get { return "IntArgEvent"; }}
355public override int yynum { get { return 127; }}
356public IntArgEvent(Parser yyp):base(yyp){}}
357//%+VectorArgEvent+128
358public class VectorArgEvent : Event{
359 public VectorArgEvent (Parser yyp, string text ):base(((LSLSyntax
360)yyp), text ){}
361
362public override string yyname { get { return "VectorArgEvent"; }}
363public override int yynum { get { return 128; }}
364public VectorArgEvent(Parser yyp):base(yyp){}}
365//%+IntRotRotArgEvent+129
366public class IntRotRotArgEvent : Event{
367 public IntRotRotArgEvent (Parser yyp, string text ):base(((LSLSyntax
368)yyp), text ){}
369
370public override string yyname { get { return "IntRotRotArgEvent"; }}
371public override int yynum { get { return 129; }}
372public IntRotRotArgEvent(Parser yyp):base(yyp){}}
373//%+IntVecVecArgEvent+130
374public class IntVecVecArgEvent : Event{
375 public IntVecVecArgEvent (Parser yyp, string text ):base(((LSLSyntax
376)yyp), text ){}
377
378public override string yyname { get { return "IntVecVecArgEvent"; }}
379public override int yynum { get { return 130; }}
380public IntVecVecArgEvent(Parser yyp):base(yyp){}}
381//%+KeyIntIntArgEvent+131
382public class KeyIntIntArgEvent : Event{
383 public KeyIntIntArgEvent (Parser yyp, string text ):base(((LSLSyntax
384)yyp), text ){}
385
386public override string yyname { get { return "KeyIntIntArgEvent"; }}
387public override int yynum { get { return 131; }}
388public KeyIntIntArgEvent(Parser yyp):base(yyp){}}
389//%+CompoundStatement+132
189public class CompoundStatement : SYMBOL{ 390public class CompoundStatement : SYMBOL{
190 public CompoundStatement (Parser yyp):base(((LSLSyntax 391 public CompoundStatement (Parser yyp):base(((LSLSyntax
191)yyp)){} 392)yyp)){}
@@ -194,9 +395,9 @@ public class CompoundStatement : SYMBOL{
194} 395}
195 396
196public override string yyname { get { return "CompoundStatement"; }} 397public override string yyname { get { return "CompoundStatement"; }}
197public override int yynum { get { return 108; }} 398public override int yynum { get { return 132; }}
198} 399}
199//%+StatementList+109 400//%+StatementList+133
200public class StatementList : SYMBOL{ 401public class StatementList : SYMBOL{
201 private void AddStatement ( Statement s ){ if ( s . kids . Top is IfStatement || s . kids . Top is WhileStatement || s . kids . Top is DoWhileStatement || s . kids . Top is ForLoop ) kids . Add ( s . kids . Pop ()); 402 private void AddStatement ( Statement s ){ if ( s . kids . Top is IfStatement || s . kids . Top is WhileStatement || s . kids . Top is DoWhileStatement || s . kids . Top is ForLoop ) kids . Add ( s . kids . Pop ());
202 else kids . Add ( s ); 403 else kids . Add ( s );
@@ -210,9 +411,9 @@ public class StatementList : SYMBOL{
210} 411}
211 412
212public override string yyname { get { return "StatementList"; }} 413public override string yyname { get { return "StatementList"; }}
213public override int yynum { get { return 109; }} 414public override int yynum { get { return 133; }}
214public StatementList(Parser yyp):base(yyp){}} 415public StatementList(Parser yyp):base(yyp){}}
215//%+Statement+110 416//%+Statement+134
216public class Statement : SYMBOL{ 417public class Statement : SYMBOL{
217 public Statement (Parser yyp, Declaration d ):base(((LSLSyntax 418 public Statement (Parser yyp, Declaration d ):base(((LSLSyntax
218)yyp)){ kids . Add ( d ); 419)yyp)){ kids . Add ( d );
@@ -258,9 +459,9 @@ public class Statement : SYMBOL{
258} 459}
259 460
260public override string yyname { get { return "Statement"; }} 461public override string yyname { get { return "Statement"; }}
261public override int yynum { get { return 110; }} 462public override int yynum { get { return 134; }}
262public Statement(Parser yyp):base(yyp){}} 463public Statement(Parser yyp):base(yyp){}}
263//%+EmptyStatement+111 464//%+EmptyStatement+135
264public class EmptyStatement : SYMBOL{ 465public class EmptyStatement : SYMBOL{
265 public EmptyStatement (Parser yyp):base(((LSLSyntax 466 public EmptyStatement (Parser yyp):base(((LSLSyntax
266)yyp)){} 467)yyp)){}
@@ -268,9 +469,9 @@ public class EmptyStatement : SYMBOL{
268} 469}
269 470
270public override string yyname { get { return "EmptyStatement"; }} 471public override string yyname { get { return "EmptyStatement"; }}
271public override int yynum { get { return 111; }} 472public override int yynum { get { return 135; }}
272} 473}
273//%+Assignment+112 474//%+Assignment+136
274public class Assignment : SYMBOL{ 475public class Assignment : SYMBOL{
275 protected string m_assignmentType ; 476 protected string m_assignmentType ;
276 public Assignment (Parser yyp, SYMBOL lhs , SYMBOL rhs , string assignmentType ):base(((LSLSyntax 477 public Assignment (Parser yyp, SYMBOL lhs , SYMBOL rhs , string assignmentType ):base(((LSLSyntax
@@ -290,9 +491,9 @@ public class Assignment : SYMBOL{
290} 491}
291 492
292public override string yyname { get { return "Assignment"; }} 493public override string yyname { get { return "Assignment"; }}
293public override int yynum { get { return 112; }} 494public override int yynum { get { return 136; }}
294public Assignment(Parser yyp):base(yyp){}} 495public Assignment(Parser yyp):base(yyp){}}
295//%+SimpleAssignment+113 496//%+SimpleAssignment+137
296public class SimpleAssignment : Assignment{ 497public class SimpleAssignment : Assignment{
297 public SimpleAssignment (Parser yyp, SYMBOL lhs , SYMBOL rhs , string assignmentType ):base(((LSLSyntax 498 public SimpleAssignment (Parser yyp, SYMBOL lhs , SYMBOL rhs , string assignmentType ):base(((LSLSyntax
298)yyp)){ m_assignmentType = assignmentType ; 499)yyp)){ m_assignmentType = assignmentType ;
@@ -302,9 +503,9 @@ public class SimpleAssignment : Assignment{
302} 503}
303 504
304public override string yyname { get { return "SimpleAssignment"; }} 505public override string yyname { get { return "SimpleAssignment"; }}
305public override int yynum { get { return 113; }} 506public override int yynum { get { return 137; }}
306public SimpleAssignment(Parser yyp):base(yyp){}} 507public SimpleAssignment(Parser yyp):base(yyp){}}
307//%+ReturnStatement+114 508//%+ReturnStatement+138
308public class ReturnStatement : SYMBOL{ 509public class ReturnStatement : SYMBOL{
309 public ReturnStatement (Parser yyp):base(((LSLSyntax 510 public ReturnStatement (Parser yyp):base(((LSLSyntax
310)yyp)){} 511)yyp)){}
@@ -314,9 +515,9 @@ public class ReturnStatement : SYMBOL{
314} 515}
315 516
316public override string yyname { get { return "ReturnStatement"; }} 517public override string yyname { get { return "ReturnStatement"; }}
317public override int yynum { get { return 114; }} 518public override int yynum { get { return 138; }}
318} 519}
319//%+JumpLabel+115 520//%+JumpLabel+139
320public class JumpLabel : SYMBOL{ 521public class JumpLabel : SYMBOL{
321 private string m_labelName ; 522 private string m_labelName ;
322 public JumpLabel (Parser yyp, string labelName ):base(((LSLSyntax 523 public JumpLabel (Parser yyp, string labelName ):base(((LSLSyntax
@@ -329,9 +530,9 @@ public class JumpLabel : SYMBOL{
329} 530}
330 531
331public override string yyname { get { return "JumpLabel"; }} 532public override string yyname { get { return "JumpLabel"; }}
332public override int yynum { get { return 115; }} 533public override int yynum { get { return 139; }}
333public JumpLabel(Parser yyp):base(yyp){}} 534public JumpLabel(Parser yyp):base(yyp){}}
334//%+JumpStatement+116 535//%+JumpStatement+140
335public class JumpStatement : SYMBOL{ 536public class JumpStatement : SYMBOL{
336 private string m_targetName ; 537 private string m_targetName ;
337 public JumpStatement (Parser yyp, string targetName ):base(((LSLSyntax 538 public JumpStatement (Parser yyp, string targetName ):base(((LSLSyntax
@@ -344,9 +545,9 @@ public class JumpStatement : SYMBOL{
344} 545}
345 546
346public override string yyname { get { return "JumpStatement"; }} 547public override string yyname { get { return "JumpStatement"; }}
347public override int yynum { get { return 116; }} 548public override int yynum { get { return 140; }}
348public JumpStatement(Parser yyp):base(yyp){}} 549public JumpStatement(Parser yyp):base(yyp){}}
349//%+StateChange+117 550//%+StateChange+141
350public class StateChange : SYMBOL{ 551public class StateChange : SYMBOL{
351 private string m_newState ; 552 private string m_newState ;
352 public StateChange (Parser yyp, string newState ):base(((LSLSyntax 553 public StateChange (Parser yyp, string newState ):base(((LSLSyntax
@@ -357,9 +558,9 @@ public class StateChange : SYMBOL{
357} 558}
358 559
359public override string yyname { get { return "StateChange"; }} 560public override string yyname { get { return "StateChange"; }}
360public override int yynum { get { return 117; }} 561public override int yynum { get { return 141; }}
361public StateChange(Parser yyp):base(yyp){}} 562public StateChange(Parser yyp):base(yyp){}}
362//%+IfStatement+118 563//%+IfStatement+142
363public class IfStatement : SYMBOL{ 564public class IfStatement : SYMBOL{
364 private void AddStatement ( Statement s ){ if (0< s . kids . Count && s . kids . Top is CompoundStatement ) kids . Add ( s . kids . Pop ()); 565 private void AddStatement ( Statement s ){ if (0< s . kids . Count && s . kids . Top is CompoundStatement ) kids . Add ( s . kids . Pop ());
365 else kids . Add ( s ); 566 else kids . Add ( s );
@@ -376,9 +577,9 @@ public class IfStatement : SYMBOL{
376} 577}
377 578
378public override string yyname { get { return "IfStatement"; }} 579public override string yyname { get { return "IfStatement"; }}
379public override int yynum { get { return 118; }} 580public override int yynum { get { return 142; }}
380public IfStatement(Parser yyp):base(yyp){}} 581public IfStatement(Parser yyp):base(yyp){}}
381//%+WhileStatement+119 582//%+WhileStatement+143
382public class WhileStatement : SYMBOL{ 583public class WhileStatement : SYMBOL{
383 public WhileStatement (Parser yyp, SYMBOL s , Statement st ):base(((LSLSyntax 584 public WhileStatement (Parser yyp, SYMBOL s , Statement st ):base(((LSLSyntax
384)yyp)){ kids . Add ( s ); 585)yyp)){ kids . Add ( s );
@@ -387,9 +588,9 @@ public class WhileStatement : SYMBOL{
387} 588}
388 589
389public override string yyname { get { return "WhileStatement"; }} 590public override string yyname { get { return "WhileStatement"; }}
390public override int yynum { get { return 119; }} 591public override int yynum { get { return 143; }}
391public WhileStatement(Parser yyp):base(yyp){}} 592public WhileStatement(Parser yyp):base(yyp){}}
392//%+DoWhileStatement+120 593//%+DoWhileStatement+144
393public class DoWhileStatement : SYMBOL{ 594public class DoWhileStatement : SYMBOL{
394 public DoWhileStatement (Parser yyp, SYMBOL s , Statement st ):base(((LSLSyntax 595 public DoWhileStatement (Parser yyp, SYMBOL s , Statement st ):base(((LSLSyntax
395)yyp)){ if (0< st . kids . Count && st . kids . Top is CompoundStatement ) kids . Add ( st . kids . Pop ()); 596)yyp)){ if (0< st . kids . Count && st . kids . Top is CompoundStatement ) kids . Add ( st . kids . Pop ());
@@ -398,9 +599,9 @@ public class DoWhileStatement : SYMBOL{
398} 599}
399 600
400public override string yyname { get { return "DoWhileStatement"; }} 601public override string yyname { get { return "DoWhileStatement"; }}
401public override int yynum { get { return 120; }} 602public override int yynum { get { return 144; }}
402public DoWhileStatement(Parser yyp):base(yyp){}} 603public DoWhileStatement(Parser yyp):base(yyp){}}
403//%+ForLoop+121 604//%+ForLoop+145
404public class ForLoop : SYMBOL{ 605public class ForLoop : SYMBOL{
405 public ForLoop (Parser yyp, ForLoopStatement flsa , Expression e , ForLoopStatement flsb , Statement s ):base(((LSLSyntax 606 public ForLoop (Parser yyp, ForLoopStatement flsa , Expression e , ForLoopStatement flsb , Statement s ):base(((LSLSyntax
406)yyp)){ kids . Add ( flsa ); 607)yyp)){ kids . Add ( flsa );
@@ -411,9 +612,9 @@ public class ForLoop : SYMBOL{
411} 612}
412 613
413public override string yyname { get { return "ForLoop"; }} 614public override string yyname { get { return "ForLoop"; }}
414public override int yynum { get { return 121; }} 615public override int yynum { get { return 145; }}
415public ForLoop(Parser yyp):base(yyp){}} 616public ForLoop(Parser yyp):base(yyp){}}
416//%+ForLoopStatement+122 617//%+ForLoopStatement+146
417public class ForLoopStatement : SYMBOL{ 618public class ForLoopStatement : SYMBOL{
418 public ForLoopStatement (Parser yyp, Expression e ):base(((LSLSyntax 619 public ForLoopStatement (Parser yyp, Expression e ):base(((LSLSyntax
419)yyp)){ kids . Add ( e ); 620)yyp)){ kids . Add ( e );
@@ -431,9 +632,9 @@ public class ForLoopStatement : SYMBOL{
431} 632}
432 633
433public override string yyname { get { return "ForLoopStatement"; }} 634public override string yyname { get { return "ForLoopStatement"; }}
434public override int yynum { get { return 122; }} 635public override int yynum { get { return 146; }}
435public ForLoopStatement(Parser yyp):base(yyp){}} 636public ForLoopStatement(Parser yyp):base(yyp){}}
436//%+FunctionCall+123 637//%+FunctionCall+147
437public class FunctionCall : SYMBOL{ 638public class FunctionCall : SYMBOL{
438 private string m_id ; 639 private string m_id ;
439 public FunctionCall (Parser yyp, string id , ArgumentList al ):base(((LSLSyntax 640 public FunctionCall (Parser yyp, string id , ArgumentList al ):base(((LSLSyntax
@@ -447,9 +648,9 @@ public class FunctionCall : SYMBOL{
447} 648}
448 649
449public override string yyname { get { return "FunctionCall"; }} 650public override string yyname { get { return "FunctionCall"; }}
450public override int yynum { get { return 123; }} 651public override int yynum { get { return 147; }}
451public FunctionCall(Parser yyp):base(yyp){}} 652public FunctionCall(Parser yyp):base(yyp){}}
452//%+ArgumentList+124 653//%+ArgumentList+148
453public class ArgumentList : SYMBOL{ 654public class ArgumentList : SYMBOL{
454 public ArgumentList (Parser yyp, Argument a ):base(((LSLSyntax 655 public ArgumentList (Parser yyp, Argument a ):base(((LSLSyntax
455)yyp)){ AddArgument ( a ); 656)yyp)){ AddArgument ( a );
@@ -463,14 +664,14 @@ public class ArgumentList : SYMBOL{
463} 664}
464 665
465public override string yyname { get { return "ArgumentList"; }} 666public override string yyname { get { return "ArgumentList"; }}
466public override int yynum { get { return 124; }} 667public override int yynum { get { return 148; }}
467public ArgumentList(Parser yyp):base(yyp){}} 668public ArgumentList(Parser yyp):base(yyp){}}
468//%+Argument+125 669//%+Argument+149
469public class Argument : SYMBOL{ 670public class Argument : SYMBOL{
470public override string yyname { get { return "Argument"; }} 671public override string yyname { get { return "Argument"; }}
471public override int yynum { get { return 125; }} 672public override int yynum { get { return 149; }}
472public Argument(Parser yyp):base(yyp){}} 673public Argument(Parser yyp):base(yyp){}}
473//%+ExpressionArgument+126 674//%+ExpressionArgument+150
474public class ExpressionArgument : Argument{ 675public class ExpressionArgument : Argument{
475 public ExpressionArgument (Parser yyp, Expression e ):base(((LSLSyntax 676 public ExpressionArgument (Parser yyp, Expression e ):base(((LSLSyntax
476)yyp)){ if ( e is ConstantExpression ) while (0< e . kids . Count ) kids . Add ( e . kids . Pop ()); 677)yyp)){ if ( e is ConstantExpression ) while (0< e . kids . Count ) kids . Add ( e . kids . Pop ());
@@ -478,9 +679,9 @@ public class ExpressionArgument : Argument{
478} 679}
479 680
480public override string yyname { get { return "ExpressionArgument"; }} 681public override string yyname { get { return "ExpressionArgument"; }}
481public override int yynum { get { return 126; }} 682public override int yynum { get { return 150; }}
482public ExpressionArgument(Parser yyp):base(yyp){}} 683public ExpressionArgument(Parser yyp):base(yyp){}}
483//%+Constant+127 684//%+Constant+151
484public class Constant : SYMBOL{ 685public class Constant : SYMBOL{
485 private string m_type ; 686 private string m_type ;
486 private string m_val ; 687 private string m_val ;
@@ -502,9 +703,9 @@ public class Constant : SYMBOL{
502} 703}
503 704
504public override string yyname { get { return "Constant"; }} 705public override string yyname { get { return "Constant"; }}
505public override int yynum { get { return 127; }} 706public override int yynum { get { return 151; }}
506public Constant(Parser yyp):base(yyp){}} 707public Constant(Parser yyp):base(yyp){}}
507//%+VectorConstant+128 708//%+VectorConstant+152
508public class VectorConstant : Constant{ 709public class VectorConstant : Constant{
509 public VectorConstant (Parser yyp, Expression valX , Expression valY , Expression valZ ):base(((LSLSyntax 710 public VectorConstant (Parser yyp, Expression valX , Expression valY , Expression valZ ):base(((LSLSyntax
510)yyp),"vector", null ){ kids . Add ( valX ); 711)yyp),"vector", null ){ kids . Add ( valX );
@@ -513,9 +714,9 @@ public class VectorConstant : Constant{
513} 714}
514 715
515public override string yyname { get { return "VectorConstant"; }} 716public override string yyname { get { return "VectorConstant"; }}
516public override int yynum { get { return 128; }} 717public override int yynum { get { return 152; }}
517public VectorConstant(Parser yyp):base(yyp){}} 718public VectorConstant(Parser yyp):base(yyp){}}
518//%+RotationConstant+129 719//%+RotationConstant+153
519public class RotationConstant : Constant{ 720public class RotationConstant : Constant{
520 public RotationConstant (Parser yyp, Expression valX , Expression valY , Expression valZ , Expression valS ):base(((LSLSyntax 721 public RotationConstant (Parser yyp, Expression valX , Expression valY , Expression valZ , Expression valS ):base(((LSLSyntax
521)yyp),"rotation", null ){ kids . Add ( valX ); 722)yyp),"rotation", null ){ kids . Add ( valX );
@@ -525,36 +726,36 @@ public class RotationConstant : Constant{
525} 726}
526 727
527public override string yyname { get { return "RotationConstant"; }} 728public override string yyname { get { return "RotationConstant"; }}
528public override int yynum { get { return 129; }} 729public override int yynum { get { return 153; }}
529public RotationConstant(Parser yyp):base(yyp){}} 730public RotationConstant(Parser yyp):base(yyp){}}
530//%+ListConstant+130 731//%+ListConstant+154
531public class ListConstant : Constant{ 732public class ListConstant : Constant{
532 public ListConstant (Parser yyp, ArgumentList al ):base(((LSLSyntax 733 public ListConstant (Parser yyp, ArgumentList al ):base(((LSLSyntax
533)yyp),"list", null ){ kids . Add ( al ); 734)yyp),"list", null ){ kids . Add ( al );
534} 735}
535 736
536public override string yyname { get { return "ListConstant"; }} 737public override string yyname { get { return "ListConstant"; }}
537public override int yynum { get { return 130; }} 738public override int yynum { get { return 154; }}
538public ListConstant(Parser yyp):base(yyp){}} 739public ListConstant(Parser yyp):base(yyp){}}
539//%+Expression+131 740//%+Expression+155
540public class Expression : SYMBOL{ 741public class Expression : SYMBOL{
541 protected void AddExpression ( Expression e ){ if ( e is ConstantExpression ) while (0< e . kids . Count ) kids . Add ( e . kids . Pop ()); 742 protected void AddExpression ( Expression e ){ if ( e is ConstantExpression ) while (0< e . kids . Count ) kids . Add ( e . kids . Pop ());
542 else kids . Add ( e ); 743 else kids . Add ( e );
543} 744}
544 745
545public override string yyname { get { return "Expression"; }} 746public override string yyname { get { return "Expression"; }}
546public override int yynum { get { return 131; }} 747public override int yynum { get { return 155; }}
547public Expression(Parser yyp):base(yyp){}} 748public Expression(Parser yyp):base(yyp){}}
548//%+ConstantExpression+132 749//%+ConstantExpression+156
549public class ConstantExpression : Expression{ 750public class ConstantExpression : Expression{
550 public ConstantExpression (Parser yyp, Constant c ):base(((LSLSyntax 751 public ConstantExpression (Parser yyp, Constant c ):base(((LSLSyntax
551)yyp)){ kids . Add ( c ); 752)yyp)){ kids . Add ( c );
552} 753}
553 754
554public override string yyname { get { return "ConstantExpression"; }} 755public override string yyname { get { return "ConstantExpression"; }}
555public override int yynum { get { return 132; }} 756public override int yynum { get { return 156; }}
556public ConstantExpression(Parser yyp):base(yyp){}} 757public ConstantExpression(Parser yyp):base(yyp){}}
557//%+IdentExpression+133 758//%+IdentExpression+157
558public class IdentExpression : Expression{ 759public class IdentExpression : Expression{
559 protected string m_name ; 760 protected string m_name ;
560 public IdentExpression (Parser yyp, string name ):base(((LSLSyntax 761 public IdentExpression (Parser yyp, string name ):base(((LSLSyntax
@@ -567,9 +768,9 @@ public class IdentExpression : Expression{
567} 768}
568 769
569public override string yyname { get { return "IdentExpression"; }} 770public override string yyname { get { return "IdentExpression"; }}
570public override int yynum { get { return 133; }} 771public override int yynum { get { return 157; }}
571public IdentExpression(Parser yyp):base(yyp){}} 772public IdentExpression(Parser yyp):base(yyp){}}
572//%+IdentDotExpression+134 773//%+IdentDotExpression+158
573public class IdentDotExpression : IdentExpression{ 774public class IdentDotExpression : IdentExpression{
574 private string m_member ; 775 private string m_member ;
575 public IdentDotExpression (Parser yyp, string name , string member ):base(((LSLSyntax 776 public IdentDotExpression (Parser yyp, string name , string member ):base(((LSLSyntax
@@ -583,18 +784,18 @@ public class IdentDotExpression : IdentExpression{
583} 784}
584 785
585public override string yyname { get { return "IdentDotExpression"; }} 786public override string yyname { get { return "IdentDotExpression"; }}
586public override int yynum { get { return 134; }} 787public override int yynum { get { return 158; }}
587public IdentDotExpression(Parser yyp):base(yyp){}} 788public IdentDotExpression(Parser yyp):base(yyp){}}
588//%+FunctionCallExpression+135 789//%+FunctionCallExpression+159
589public class FunctionCallExpression : Expression{ 790public class FunctionCallExpression : Expression{
590 public FunctionCallExpression (Parser yyp, FunctionCall fc ):base(((LSLSyntax 791 public FunctionCallExpression (Parser yyp, FunctionCall fc ):base(((LSLSyntax
591)yyp)){ kids . Add ( fc ); 792)yyp)){ kids . Add ( fc );
592} 793}
593 794
594public override string yyname { get { return "FunctionCallExpression"; }} 795public override string yyname { get { return "FunctionCallExpression"; }}
595public override int yynum { get { return 135; }} 796public override int yynum { get { return 159; }}
596public FunctionCallExpression(Parser yyp):base(yyp){}} 797public FunctionCallExpression(Parser yyp):base(yyp){}}
597//%+BinaryExpression+136 798//%+BinaryExpression+160
598public class BinaryExpression : Expression{ 799public class BinaryExpression : Expression{
599 private string m_expressionSymbol ; 800 private string m_expressionSymbol ;
600 public BinaryExpression (Parser yyp, Expression lhs , Expression rhs , string expressionSymbol ):base(((LSLSyntax 801 public BinaryExpression (Parser yyp, Expression lhs , Expression rhs , string expressionSymbol ):base(((LSLSyntax
@@ -609,9 +810,9 @@ public class BinaryExpression : Expression{
609} 810}
610 811
611public override string yyname { get { return "BinaryExpression"; }} 812public override string yyname { get { return "BinaryExpression"; }}
612public override int yynum { get { return 136; }} 813public override int yynum { get { return 160; }}
613public BinaryExpression(Parser yyp):base(yyp){}} 814public BinaryExpression(Parser yyp):base(yyp){}}
614//%+UnaryExpression+137 815//%+UnaryExpression+161
615public class UnaryExpression : Expression{ 816public class UnaryExpression : Expression{
616 private string m_unarySymbol ; 817 private string m_unarySymbol ;
617 public UnaryExpression (Parser yyp, string unarySymbol , Expression e ):base(((LSLSyntax 818 public UnaryExpression (Parser yyp, string unarySymbol , Expression e ):base(((LSLSyntax
@@ -625,9 +826,9 @@ public class UnaryExpression : Expression{
625} 826}
626 827
627public override string yyname { get { return "UnaryExpression"; }} 828public override string yyname { get { return "UnaryExpression"; }}
628public override int yynum { get { return 137; }} 829public override int yynum { get { return 161; }}
629public UnaryExpression(Parser yyp):base(yyp){}} 830public UnaryExpression(Parser yyp):base(yyp){}}
630//%+TypecastExpression+138 831//%+TypecastExpression+162
631public class TypecastExpression : Expression{ 832public class TypecastExpression : Expression{
632 private string m_typecastType ; 833 private string m_typecastType ;
633 public TypecastExpression (Parser yyp, string typecastType , SYMBOL rhs ):base(((LSLSyntax 834 public TypecastExpression (Parser yyp, string typecastType , SYMBOL rhs ):base(((LSLSyntax
@@ -641,18 +842,18 @@ public class TypecastExpression : Expression{
641} 842}
642 843
643public override string yyname { get { return "TypecastExpression"; }} 844public override string yyname { get { return "TypecastExpression"; }}
644public override int yynum { get { return 138; }} 845public override int yynum { get { return 162; }}
645public TypecastExpression(Parser yyp):base(yyp){}} 846public TypecastExpression(Parser yyp):base(yyp){}}
646//%+ParenthesisExpression+139 847//%+ParenthesisExpression+163
647public class ParenthesisExpression : Expression{ 848public class ParenthesisExpression : Expression{
648 public ParenthesisExpression (Parser yyp, SYMBOL s ):base(((LSLSyntax 849 public ParenthesisExpression (Parser yyp, SYMBOL s ):base(((LSLSyntax
649)yyp)){ kids . Add ( s ); 850)yyp)){ kids . Add ( s );
650} 851}
651 852
652public override string yyname { get { return "ParenthesisExpression"; }} 853public override string yyname { get { return "ParenthesisExpression"; }}
653public override int yynum { get { return 139; }} 854public override int yynum { get { return 163; }}
654public ParenthesisExpression(Parser yyp):base(yyp){}} 855public ParenthesisExpression(Parser yyp):base(yyp){}}
655//%+IncrementDecrementExpression+140 856//%+IncrementDecrementExpression+164
656public class IncrementDecrementExpression : Expression{ 857public class IncrementDecrementExpression : Expression{
657 private string m_name ; 858 private string m_name ;
658 private string m_operation ; 859 private string m_operation ;
@@ -680,7 +881,7 @@ public class IncrementDecrementExpression : Expression{
680} 881}
681 882
682public override string yyname { get { return "IncrementDecrementExpression"; }} 883public override string yyname { get { return "IncrementDecrementExpression"; }}
683public override int yynum { get { return 140; }} 884public override int yynum { get { return 164; }}
684public IncrementDecrementExpression(Parser yyp):base(yyp){}} 885public IncrementDecrementExpression(Parser yyp):base(yyp){}}
685 886
686public class LSLProgramRoot_1 : LSLProgramRoot { 887public class LSLProgramRoot_1 : LSLProgramRoot {
@@ -792,6 +993,90 @@ public class StateBody_2 : StateBody {
792 ((StateEvent)(yyq.StackAt(0).m_value)) 993 ((StateEvent)(yyq.StackAt(0).m_value))
793 ){}} 994 ){}}
794 995
996public class StateBody_3 : StateBody {
997 public StateBody_3(Parser yyq):base(yyq,
998 ((VoidArgStateEvent)(yyq.StackAt(0).m_value))
999 ){}}
1000
1001public class StateBody_4 : StateBody {
1002 public StateBody_4(Parser yyq):base(yyq,
1003 ((StateBody)(yyq.StackAt(1).m_value))
1004 ,
1005 ((VoidArgStateEvent)(yyq.StackAt(0).m_value))
1006 ){}}
1007
1008public class StateBody_5 : StateBody {
1009 public StateBody_5(Parser yyq):base(yyq,
1010 ((KeyArgStateEvent)(yyq.StackAt(0).m_value))
1011 ){}}
1012
1013public class StateBody_6 : StateBody {
1014 public StateBody_6(Parser yyq):base(yyq,
1015 ((StateBody)(yyq.StackAt(1).m_value))
1016 ,
1017 ((KeyArgStateEvent)(yyq.StackAt(0).m_value))
1018 ){}}
1019
1020public class StateBody_7 : StateBody {
1021 public StateBody_7(Parser yyq):base(yyq,
1022 ((IntArgStateEvent)(yyq.StackAt(0).m_value))
1023 ){}}
1024
1025public class StateBody_8 : StateBody {
1026 public StateBody_8(Parser yyq):base(yyq,
1027 ((StateBody)(yyq.StackAt(1).m_value))
1028 ,
1029 ((IntArgStateEvent)(yyq.StackAt(0).m_value))
1030 ){}}
1031
1032public class StateBody_9 : StateBody {
1033 public StateBody_9(Parser yyq):base(yyq,
1034 ((VectorArgStateEvent)(yyq.StackAt(0).m_value))
1035 ){}}
1036
1037public class StateBody_10 : StateBody {
1038 public StateBody_10(Parser yyq):base(yyq,
1039 ((StateBody)(yyq.StackAt(1).m_value))
1040 ,
1041 ((VectorArgStateEvent)(yyq.StackAt(0).m_value))
1042 ){}}
1043
1044public class StateBody_11 : StateBody {
1045 public StateBody_11(Parser yyq):base(yyq,
1046 ((IntRotRotArgStateEvent)(yyq.StackAt(0).m_value))
1047 ){}}
1048
1049public class StateBody_12 : StateBody {
1050 public StateBody_12(Parser yyq):base(yyq,
1051 ((StateBody)(yyq.StackAt(1).m_value))
1052 ,
1053 ((IntRotRotArgStateEvent)(yyq.StackAt(0).m_value))
1054 ){}}
1055
1056public class StateBody_13 : StateBody {
1057 public StateBody_13(Parser yyq):base(yyq,
1058 ((IntVecVecArgStateEvent)(yyq.StackAt(0).m_value))
1059 ){}}
1060
1061public class StateBody_14 : StateBody {
1062 public StateBody_14(Parser yyq):base(yyq,
1063 ((StateBody)(yyq.StackAt(1).m_value))
1064 ,
1065 ((IntVecVecArgStateEvent)(yyq.StackAt(0).m_value))
1066 ){}}
1067
1068public class StateBody_15 : StateBody {
1069 public StateBody_15(Parser yyq):base(yyq,
1070 ((KeyIntIntArgStateEvent)(yyq.StackAt(0).m_value))
1071 ){}}
1072
1073public class StateBody_16 : StateBody {
1074 public StateBody_16(Parser yyq):base(yyq,
1075 ((StateBody)(yyq.StackAt(1).m_value))
1076 ,
1077 ((KeyIntIntArgStateEvent)(yyq.StackAt(0).m_value))
1078 ){}}
1079
795public class StateEvent_1 : StateEvent { 1080public class StateEvent_1 : StateEvent {
796 public StateEvent_1(Parser yyq):base(yyq, 1081 public StateEvent_1(Parser yyq):base(yyq,
797 ((Event)(yyq.StackAt(4).m_value)) 1082 ((Event)(yyq.StackAt(4).m_value))
@@ -801,6 +1086,67 @@ public class StateEvent_1 : StateEvent {
801 ((CompoundStatement)(yyq.StackAt(0).m_value)) 1086 ((CompoundStatement)(yyq.StackAt(0).m_value))
802 ){}} 1087 ){}}
803 1088
1089public class VoidArgStateEvent_1 : VoidArgStateEvent {
1090 public VoidArgStateEvent_1(Parser yyq):base(yyq,
1091 ((VoidArgEvent)(yyq.StackAt(3).m_value))
1092 .yytext,
1093 ((CompoundStatement)(yyq.StackAt(0).m_value))
1094 ){}}
1095
1096public class KeyArgStateEvent_1 : KeyArgStateEvent {
1097 public KeyArgStateEvent_1(Parser yyq):base(yyq,
1098 ((KeyArgEvent)(yyq.StackAt(4).m_value))
1099 .yytext,
1100 ((KeyArgumentDeclarationList)(yyq.StackAt(2).m_value))
1101 ,
1102 ((CompoundStatement)(yyq.StackAt(0).m_value))
1103 ){}}
1104
1105public class IntArgStateEvent_1 : IntArgStateEvent {
1106 public IntArgStateEvent_1(Parser yyq):base(yyq,
1107 ((IntArgEvent)(yyq.StackAt(4).m_value))
1108 .yytext,
1109 ((IntArgumentDeclarationList)(yyq.StackAt(2).m_value))
1110 ,
1111 ((CompoundStatement)(yyq.StackAt(0).m_value))
1112 ){}}
1113
1114public class VectorArgStateEvent_1 : VectorArgStateEvent {
1115 public VectorArgStateEvent_1(Parser yyq):base(yyq,
1116 ((VectorArgEvent)(yyq.StackAt(4).m_value))
1117 .yytext,
1118 ((VectorArgumentDeclarationList)(yyq.StackAt(2).m_value))
1119 ,
1120 ((CompoundStatement)(yyq.StackAt(0).m_value))
1121 ){}}
1122
1123public class IntRotRotArgStateEvent_1 : IntRotRotArgStateEvent {
1124 public IntRotRotArgStateEvent_1(Parser yyq):base(yyq,
1125 ((IntRotRotArgEvent)(yyq.StackAt(4).m_value))
1126 .yytext,
1127 ((IntRotRotArgumentDeclarationList)(yyq.StackAt(2).m_value))
1128 ,
1129 ((CompoundStatement)(yyq.StackAt(0).m_value))
1130 ){}}
1131
1132public class IntVecVecArgStateEvent_1 : IntVecVecArgStateEvent {
1133 public IntVecVecArgStateEvent_1(Parser yyq):base(yyq,
1134 ((IntVecVecArgEvent)(yyq.StackAt(4).m_value))
1135 .yytext,
1136 ((IntVecVecArgumentDeclarationList)(yyq.StackAt(2).m_value))
1137 ,
1138 ((CompoundStatement)(yyq.StackAt(0).m_value))
1139 ){}}
1140
1141public class KeyIntIntArgStateEvent_1 : KeyIntIntArgStateEvent {
1142 public KeyIntIntArgStateEvent_1(Parser yyq):base(yyq,
1143 ((KeyIntIntArgEvent)(yyq.StackAt(4).m_value))
1144 .yytext,
1145 ((KeyIntIntArgumentDeclarationList)(yyq.StackAt(2).m_value))
1146 ,
1147 ((CompoundStatement)(yyq.StackAt(0).m_value))
1148 ){}}
1149
804public class ArgumentDeclarationList_1 : ArgumentDeclarationList { 1150public class ArgumentDeclarationList_1 : ArgumentDeclarationList {
805 public ArgumentDeclarationList_1(Parser yyq):base(yyq, 1151 public ArgumentDeclarationList_1(Parser yyq):base(yyq,
806 ((Declaration)(yyq.StackAt(0).m_value)) 1152 ((Declaration)(yyq.StackAt(0).m_value))
@@ -813,6 +1159,48 @@ public class ArgumentDeclarationList_2 : ArgumentDeclarationList {
813 ((Declaration)(yyq.StackAt(0).m_value)) 1159 ((Declaration)(yyq.StackAt(0).m_value))
814 ){}} 1160 ){}}
815 1161
1162public class KeyArgumentDeclarationList_1 : KeyArgumentDeclarationList {
1163 public KeyArgumentDeclarationList_1(Parser yyq):base(yyq,
1164 ((KeyDeclaration)(yyq.StackAt(0).m_value))
1165 ){}}
1166
1167public class IntArgumentDeclarationList_1 : IntArgumentDeclarationList {
1168 public IntArgumentDeclarationList_1(Parser yyq):base(yyq,
1169 ((IntDeclaration)(yyq.StackAt(0).m_value))
1170 ){}}
1171
1172public class VectorArgumentDeclarationList_1 : VectorArgumentDeclarationList {
1173 public VectorArgumentDeclarationList_1(Parser yyq):base(yyq,
1174 ((VecDeclaration)(yyq.StackAt(0).m_value))
1175 ){}}
1176
1177public class IntRotRotArgumentDeclarationList_1 : IntRotRotArgumentDeclarationList {
1178 public IntRotRotArgumentDeclarationList_1(Parser yyq):base(yyq,
1179 ((IntDeclaration)(yyq.StackAt(4).m_value))
1180 ,
1181 ((RotDeclaration)(yyq.StackAt(2).m_value))
1182 ,
1183 ((RotDeclaration)(yyq.StackAt(0).m_value))
1184 ){}}
1185
1186public class IntVecVecArgumentDeclarationList_1 : IntVecVecArgumentDeclarationList {
1187 public IntVecVecArgumentDeclarationList_1(Parser yyq):base(yyq,
1188 ((IntDeclaration)(yyq.StackAt(4).m_value))
1189 ,
1190 ((VecDeclaration)(yyq.StackAt(2).m_value))
1191 ,
1192 ((VecDeclaration)(yyq.StackAt(0).m_value))
1193 ){}}
1194
1195public class KeyIntIntArgumentDeclarationList_1 : KeyIntIntArgumentDeclarationList {
1196 public KeyIntIntArgumentDeclarationList_1(Parser yyq):base(yyq,
1197 ((KeyDeclaration)(yyq.StackAt(4).m_value))
1198 ,
1199 ((IntDeclaration)(yyq.StackAt(2).m_value))
1200 ,
1201 ((IntDeclaration)(yyq.StackAt(0).m_value))
1202 ){}}
1203
816public class Declaration_1 : Declaration { 1204public class Declaration_1 : Declaration {
817 public Declaration_1(Parser yyq):base(yyq, 1205 public Declaration_1(Parser yyq):base(yyq,
818 ((Typename)(yyq.StackAt(1).m_value)) 1206 ((Typename)(yyq.StackAt(1).m_value))
@@ -820,6 +1208,34 @@ public class Declaration_1 : Declaration {
820 ((IDENT)(yyq.StackAt(0).m_value)) 1208 ((IDENT)(yyq.StackAt(0).m_value))
821 .yytext){}} 1209 .yytext){}}
822 1210
1211public class KeyDeclaration_1 : KeyDeclaration {
1212 public KeyDeclaration_1(Parser yyq):base(yyq,
1213 ((KEY_TYPE)(yyq.StackAt(1).m_value))
1214 .yytext,
1215 ((IDENT)(yyq.StackAt(0).m_value))
1216 .yytext){}}
1217
1218public class IntDeclaration_1 : IntDeclaration {
1219 public IntDeclaration_1(Parser yyq):base(yyq,
1220 ((INTEGER_TYPE)(yyq.StackAt(1).m_value))
1221 .yytext,
1222 ((IDENT)(yyq.StackAt(0).m_value))
1223 .yytext){}}
1224
1225public class VecDeclaration_1 : VecDeclaration {
1226 public VecDeclaration_1(Parser yyq):base(yyq,
1227 ((VECTOR_TYPE)(yyq.StackAt(1).m_value))
1228 .yytext,
1229 ((IDENT)(yyq.StackAt(0).m_value))
1230 .yytext){}}
1231
1232public class RotDeclaration_1 : RotDeclaration {
1233 public RotDeclaration_1(Parser yyq):base(yyq,
1234 ((ROTATION_TYPE)(yyq.StackAt(1).m_value))
1235 .yytext,
1236 ((IDENT)(yyq.StackAt(0).m_value))
1237 .yytext){}}
1238
823public class CompoundStatement_1 : CompoundStatement { 1239public class CompoundStatement_1 : CompoundStatement {
824 public CompoundStatement_1(Parser yyq):base(yyq){}} 1240 public CompoundStatement_1(Parser yyq):base(yyq){}}
825 1241
@@ -1780,172 +2196,172 @@ public class Typename_7 : Typename {
1780 2196
1781public class Event_1 : Event { 2197public class Event_1 : Event {
1782 public Event_1(Parser yyq):base(yyq, 2198 public Event_1(Parser yyq):base(yyq,
1783 ((AT_ROT_TARGET_EVENT)(yyq.StackAt(0).m_value)) 2199 ((DATASERVER_EVENT)(yyq.StackAt(0).m_value))
1784 .yytext){}} 2200 .yytext){}}
1785 2201
1786public class Event_2 : Event { 2202public class Event_2 : Event {
1787 public Event_2(Parser yyq):base(yyq, 2203 public Event_2(Parser yyq):base(yyq,
1788 ((AT_TARGET_EVENT)(yyq.StackAt(0).m_value)) 2204 ((EMAIL_EVENT)(yyq.StackAt(0).m_value))
1789 .yytext){}} 2205 .yytext){}}
1790 2206
1791public class Event_3 : Event { 2207public class Event_3 : Event {
1792 public Event_3(Parser yyq):base(yyq, 2208 public Event_3(Parser yyq):base(yyq,
1793 ((ATTACH_EVENT)(yyq.StackAt(0).m_value)) 2209 ((HTTP_RESPONSE_EVENT)(yyq.StackAt(0).m_value))
1794 .yytext){}} 2210 .yytext){}}
1795 2211
1796public class Event_4 : Event { 2212public class Event_4 : Event {
1797 public Event_4(Parser yyq):base(yyq, 2213 public Event_4(Parser yyq):base(yyq,
1798 ((CHANGED_EVENT)(yyq.StackAt(0).m_value)) 2214 ((LINK_MESSAGE_EVENT)(yyq.StackAt(0).m_value))
1799 .yytext){}} 2215 .yytext){}}
1800 2216
1801public class Event_5 : Event { 2217public class Event_5 : Event {
1802 public Event_5(Parser yyq):base(yyq, 2218 public Event_5(Parser yyq):base(yyq,
1803 ((COLLISION_EVENT)(yyq.StackAt(0).m_value)) 2219 ((LISTEN_EVENT)(yyq.StackAt(0).m_value))
1804 .yytext){}} 2220 .yytext){}}
1805 2221
1806public class Event_6 : Event { 2222public class Event_6 : Event {
1807 public Event_6(Parser yyq):base(yyq, 2223 public Event_6(Parser yyq):base(yyq,
1808 ((COLLISION_END_EVENT)(yyq.StackAt(0).m_value)) 2224 ((MONEY_EVENT)(yyq.StackAt(0).m_value))
1809 .yytext){}} 2225 .yytext){}}
1810 2226
1811public class Event_7 : Event { 2227public class Event_7 : Event {
1812 public Event_7(Parser yyq):base(yyq, 2228 public Event_7(Parser yyq):base(yyq,
1813 ((COLLISION_START_EVENT)(yyq.StackAt(0).m_value)) 2229 ((REMOTE_DATA_EVENT)(yyq.StackAt(0).m_value))
1814 .yytext){}} 2230 .yytext){}}
1815 2231
1816public class Event_8 : Event { 2232public class Event_8 : Event {
1817 public Event_8(Parser yyq):base(yyq, 2233 public Event_8(Parser yyq):base(yyq,
1818 ((CONTROL_EVENT)(yyq.StackAt(0).m_value)) 2234 ((HTTP_REQUEST_EVENT)(yyq.StackAt(0).m_value))
1819 .yytext){}} 2235 .yytext){}}
1820 2236
1821public class Event_9 : Event { 2237public class VoidArgEvent_1 : VoidArgEvent {
1822 public Event_9(Parser yyq):base(yyq, 2238 public VoidArgEvent_1(Parser yyq):base(yyq,
1823 ((DATASERVER_EVENT)(yyq.StackAt(0).m_value)) 2239 ((STATE_ENTRY_EVENT)(yyq.StackAt(0).m_value))
1824 .yytext){}} 2240 .yytext){}}
1825 2241
1826public class Event_10 : Event { 2242public class VoidArgEvent_2 : VoidArgEvent {
1827 public Event_10(Parser yyq):base(yyq, 2243 public VoidArgEvent_2(Parser yyq):base(yyq,
1828 ((EMAIL_EVENT)(yyq.StackAt(0).m_value)) 2244 ((STATE_EXIT_EVENT)(yyq.StackAt(0).m_value))
1829 .yytext){}} 2245 .yytext){}}
1830 2246
1831public class Event_11 : Event { 2247public class VoidArgEvent_3 : VoidArgEvent {
1832 public Event_11(Parser yyq):base(yyq, 2248 public VoidArgEvent_3(Parser yyq):base(yyq,
1833 ((HTTP_RESPONSE_EVENT)(yyq.StackAt(0).m_value)) 2249 ((MOVING_END_EVENT)(yyq.StackAt(0).m_value))
1834 .yytext){}} 2250 .yytext){}}
1835 2251
1836public class Event_12 : Event { 2252public class VoidArgEvent_4 : VoidArgEvent {
1837 public Event_12(Parser yyq):base(yyq, 2253 public VoidArgEvent_4(Parser yyq):base(yyq,
1838 ((LAND_COLLISION_EVENT)(yyq.StackAt(0).m_value)) 2254 ((MOVING_START_EVENT)(yyq.StackAt(0).m_value))
1839 .yytext){}} 2255 .yytext){}}
1840 2256
1841public class Event_13 : Event { 2257public class VoidArgEvent_5 : VoidArgEvent {
1842 public Event_13(Parser yyq):base(yyq, 2258 public VoidArgEvent_5(Parser yyq):base(yyq,
1843 ((LAND_COLLISION_END_EVENT)(yyq.StackAt(0).m_value)) 2259 ((NO_SENSOR_EVENT)(yyq.StackAt(0).m_value))
1844 .yytext){}} 2260 .yytext){}}
1845 2261
1846public class Event_14 : Event { 2262public class VoidArgEvent_6 : VoidArgEvent {
1847 public Event_14(Parser yyq):base(yyq, 2263 public VoidArgEvent_6(Parser yyq):base(yyq,
1848 ((LAND_COLLISION_START_EVENT)(yyq.StackAt(0).m_value)) 2264 ((NOT_AT_ROT_TARGET_EVENT)(yyq.StackAt(0).m_value))
1849 .yytext){}} 2265 .yytext){}}
1850 2266
1851public class Event_15 : Event { 2267public class VoidArgEvent_7 : VoidArgEvent {
1852 public Event_15(Parser yyq):base(yyq, 2268 public VoidArgEvent_7(Parser yyq):base(yyq,
1853 ((LINK_MESSAGE_EVENT)(yyq.StackAt(0).m_value)) 2269 ((NOT_AT_TARGET_EVENT)(yyq.StackAt(0).m_value))
1854 .yytext){}} 2270 .yytext){}}
1855 2271
1856public class Event_16 : Event { 2272public class VoidArgEvent_8 : VoidArgEvent {
1857 public Event_16(Parser yyq):base(yyq, 2273 public VoidArgEvent_8(Parser yyq):base(yyq,
1858 ((LISTEN_EVENT)(yyq.StackAt(0).m_value)) 2274 ((TIMER_EVENT)(yyq.StackAt(0).m_value))
1859 .yytext){}} 2275 .yytext){}}
1860 2276
1861public class Event_17 : Event { 2277public class KeyArgEvent_1 : KeyArgEvent {
1862 public Event_17(Parser yyq):base(yyq, 2278 public KeyArgEvent_1(Parser yyq):base(yyq,
1863 ((MONEY_EVENT)(yyq.StackAt(0).m_value)) 2279 ((ATTACH_EVENT)(yyq.StackAt(0).m_value))
1864 .yytext){}} 2280 .yytext){}}
1865 2281
1866public class Event_18 : Event { 2282public class KeyArgEvent_2 : KeyArgEvent {
1867 public Event_18(Parser yyq):base(yyq, 2283 public KeyArgEvent_2(Parser yyq):base(yyq,
1868 ((MOVING_END_EVENT)(yyq.StackAt(0).m_value)) 2284 ((OBJECT_REZ_EVENT)(yyq.StackAt(0).m_value))
1869 .yytext){}} 2285 .yytext){}}
1870 2286
1871public class Event_19 : Event { 2287public class IntArgEvent_1 : IntArgEvent {
1872 public Event_19(Parser yyq):base(yyq, 2288 public IntArgEvent_1(Parser yyq):base(yyq,
1873 ((MOVING_START_EVENT)(yyq.StackAt(0).m_value)) 2289 ((CHANGED_EVENT)(yyq.StackAt(0).m_value))
1874 .yytext){}} 2290 .yytext){}}
1875 2291
1876public class Event_20 : Event { 2292public class IntArgEvent_2 : IntArgEvent {
1877 public Event_20(Parser yyq):base(yyq, 2293 public IntArgEvent_2(Parser yyq):base(yyq,
1878 ((NO_SENSOR_EVENT)(yyq.StackAt(0).m_value)) 2294 ((COLLISION_EVENT)(yyq.StackAt(0).m_value))
1879 .yytext){}} 2295 .yytext){}}
1880 2296
1881public class Event_21 : Event { 2297public class IntArgEvent_3 : IntArgEvent {
1882 public Event_21(Parser yyq):base(yyq, 2298 public IntArgEvent_3(Parser yyq):base(yyq,
1883 ((NOT_AT_ROT_TARGET_EVENT)(yyq.StackAt(0).m_value)) 2299 ((COLLISION_END_EVENT)(yyq.StackAt(0).m_value))
1884 .yytext){}} 2300 .yytext){}}
1885 2301
1886public class Event_22 : Event { 2302public class IntArgEvent_4 : IntArgEvent {
1887 public Event_22(Parser yyq):base(yyq, 2303 public IntArgEvent_4(Parser yyq):base(yyq,
1888 ((NOT_AT_TARGET_EVENT)(yyq.StackAt(0).m_value)) 2304 ((COLLISION_START_EVENT)(yyq.StackAt(0).m_value))
1889 .yytext){}} 2305 .yytext){}}
1890 2306
1891public class Event_23 : Event { 2307public class IntArgEvent_5 : IntArgEvent {
1892 public Event_23(Parser yyq):base(yyq, 2308 public IntArgEvent_5(Parser yyq):base(yyq,
1893 ((OBJECT_REZ_EVENT)(yyq.StackAt(0).m_value)) 2309 ((ON_REZ_EVENT)(yyq.StackAt(0).m_value))
1894 .yytext){}} 2310 .yytext){}}
1895 2311
1896public class Event_24 : Event { 2312public class IntArgEvent_6 : IntArgEvent {
1897 public Event_24(Parser yyq):base(yyq, 2313 public IntArgEvent_6(Parser yyq):base(yyq,
1898 ((ON_REZ_EVENT)(yyq.StackAt(0).m_value)) 2314 ((RUN_TIME_PERMISSIONS_EVENT)(yyq.StackAt(0).m_value))
1899 .yytext){}} 2315 .yytext){}}
1900 2316
1901public class Event_25 : Event { 2317public class IntArgEvent_7 : IntArgEvent {
1902 public Event_25(Parser yyq):base(yyq, 2318 public IntArgEvent_7(Parser yyq):base(yyq,
1903 ((REMOTE_DATA_EVENT)(yyq.StackAt(0).m_value)) 2319 ((SENSOR_EVENT)(yyq.StackAt(0).m_value))
1904 .yytext){}} 2320 .yytext){}}
1905 2321
1906public class Event_26 : Event { 2322public class IntArgEvent_8 : IntArgEvent {
1907 public Event_26(Parser yyq):base(yyq, 2323 public IntArgEvent_8(Parser yyq):base(yyq,
1908 ((RUN_TIME_PERMISSIONS_EVENT)(yyq.StackAt(0).m_value)) 2324 ((TOUCH_EVENT)(yyq.StackAt(0).m_value))
1909 .yytext){}} 2325 .yytext){}}
1910 2326
1911public class Event_27 : Event { 2327public class IntArgEvent_9 : IntArgEvent {
1912 public Event_27(Parser yyq):base(yyq, 2328 public IntArgEvent_9(Parser yyq):base(yyq,
1913 ((SENSOR_EVENT)(yyq.StackAt(0).m_value)) 2329 ((TOUCH_END_EVENT)(yyq.StackAt(0).m_value))
1914 .yytext){}} 2330 .yytext){}}
1915 2331
1916public class Event_28 : Event { 2332public class IntArgEvent_10 : IntArgEvent {
1917 public Event_28(Parser yyq):base(yyq, 2333 public IntArgEvent_10(Parser yyq):base(yyq,
1918 ((STATE_ENTRY_EVENT)(yyq.StackAt(0).m_value)) 2334 ((TOUCH_START_EVENT)(yyq.StackAt(0).m_value))
1919 .yytext){}} 2335 .yytext){}}
1920 2336
1921public class Event_29 : Event { 2337public class VectorArgEvent_1 : VectorArgEvent {
1922 public Event_29(Parser yyq):base(yyq, 2338 public VectorArgEvent_1(Parser yyq):base(yyq,
1923 ((STATE_EXIT_EVENT)(yyq.StackAt(0).m_value)) 2339 ((LAND_COLLISION_EVENT)(yyq.StackAt(0).m_value))
1924 .yytext){}} 2340 .yytext){}}
1925 2341
1926public class Event_30 : Event { 2342public class VectorArgEvent_2 : VectorArgEvent {
1927 public Event_30(Parser yyq):base(yyq, 2343 public VectorArgEvent_2(Parser yyq):base(yyq,
1928 ((TIMER_EVENT)(yyq.StackAt(0).m_value)) 2344 ((LAND_COLLISION_END_EVENT)(yyq.StackAt(0).m_value))
1929 .yytext){}} 2345 .yytext){}}
1930 2346
1931public class Event_31 : Event { 2347public class VectorArgEvent_3 : VectorArgEvent {
1932 public Event_31(Parser yyq):base(yyq, 2348 public VectorArgEvent_3(Parser yyq):base(yyq,
1933 ((TOUCH_EVENT)(yyq.StackAt(0).m_value)) 2349 ((LAND_COLLISION_START_EVENT)(yyq.StackAt(0).m_value))
1934 .yytext){}} 2350 .yytext){}}
1935 2351
1936public class Event_32 : Event { 2352public class IntRotRotArgEvent_1 : IntRotRotArgEvent {
1937 public Event_32(Parser yyq):base(yyq, 2353 public IntRotRotArgEvent_1(Parser yyq):base(yyq,
1938 ((TOUCH_END_EVENT)(yyq.StackAt(0).m_value)) 2354 ((AT_ROT_TARGET_EVENT)(yyq.StackAt(0).m_value))
1939 .yytext){}} 2355 .yytext){}}
1940 2356
1941public class Event_33 : Event { 2357public class IntVecVecArgEvent_1 : IntVecVecArgEvent {
1942 public Event_33(Parser yyq):base(yyq, 2358 public IntVecVecArgEvent_1(Parser yyq):base(yyq,
1943 ((TOUCH_START_EVENT)(yyq.StackAt(0).m_value)) 2359 ((AT_TARGET_EVENT)(yyq.StackAt(0).m_value))
1944 .yytext){}} 2360 .yytext){}}
1945 2361
1946public class Event_34 : Event { 2362public class KeyIntIntArgEvent_1 : KeyIntIntArgEvent {
1947 public Event_34(Parser yyq):base(yyq, 2363 public KeyIntIntArgEvent_1(Parser yyq):base(yyq,
1948 ((HTTP_REQUEST_EVENT)(yyq.StackAt(0).m_value)) 2364 ((CONTROL_EVENT)(yyq.StackAt(0).m_value))
1949 .yytext){}} 2365 .yytext){}}
1950public class yyLSLSyntax 2366public class yyLSLSyntax
1951: YyParser { 2367: YyParser {
@@ -1979,9 +2395,9 @@ public yyLSLSyntax
197997,0,109,0,82, 239597,0,109,0,82,
19800,111,0,111,0, 23960,111,0,111,0,
1981116,0,1,96,1, 2397116,0,1,96,1,
19822,104,18,1,2717, 23982,104,18,1,2841,
1983102,2,0,105,5, 2399102,2,0,105,5,
1984320,1,0,106,18, 2400394,1,0,106,18,
19851,0,0,2,0, 24011,0,0,2,0,
19861,1,107,18,1, 24021,1,107,18,1,
19871,108,20,109,4, 24031,108,20,109,4,
@@ -2042,7 +2458,7 @@ public yyLSLSyntax
2042121,0,112,0,101, 2458121,0,112,0,101,
20430,110,0,97,0, 24590,110,0,97,0,
2044109,0,101,0,1, 2460109,0,101,0,1,
2045106,1,2,2,0, 2461123,1,2,2,0,
20461,9,131,18,1, 24621,9,131,18,1,
20479,132,20,133,4, 24639,132,20,133,4,
204810,73,0,68,0, 246410,73,0,68,0,
@@ -2071,518 +2487,665 @@ public yyLSLSyntax
2071105,0,111,0,110, 2487105,0,111,0,110,
20720,76,0,105,0, 24880,76,0,105,0,
2073115,0,116,0,1, 2489115,0,116,0,1,
2074104,1,2,2,0, 2490111,1,2,2,0,
20751,21,142,18,1, 24911,21,142,18,1,
207621,143,20,144,4, 249221,143,20,144,4,
207710,67,0,79,0, 249310,67,0,79,0,
207877,0,77,0,65, 249477,0,77,0,65,
20790,1,14,1,1, 24950,1,14,1,1,
20802,0,1,1694,145, 24962,0,1,2807,145,
208118,1,1694,146,20, 249718,1,2807,146,20,
2082147,4,32,70,0, 2498147,4,18,83,0,
249969,0,77,0,73,
25000,67,0,79,0,
250176,0,79,0,78,
25020,1,11,1,1,
25032,0,1,1694,148,
250418,1,1694,149,20,
2505150,4,32,70,0,
2083111,0,114,0,76, 2506111,0,114,0,76,
20840,111,0,111,0, 25070,111,0,111,0,
2085112,0,83,0,116, 2508112,0,83,0,116,
20860,97,0,116,0, 25090,97,0,116,0,
2087101,0,109,0,101, 2510101,0,109,0,101,
20880,110,0,116,0, 25110,110,0,116,0,
20891,122,1,2,2, 25121,146,1,2,2,
20900,1,1695,148,18, 25130,1,1695,151,18,
20911,1695,143,2,0, 25141,1695,143,2,0,
20921,30,149,18,1, 25151,2645,152,18,1,
209330,150,20,151,4, 25162645,153,20,154,4,
209422,68,0,101,0, 251734,86,0,111,0,
2518105,0,100,0,65,
25190,114,0,103,0,
252083,0,116,0,97,
25210,116,0,101,0,
252269,0,118,0,101,
25230,110,0,116,0,
25241,104,1,2,2,
25250,1,2646,155,18,
25261,2646,156,20,157,
25274,20,83,0,116,
25280,97,0,116,0,
2529101,0,69,0,118,
25300,101,0,110,0,
2531116,0,1,103,1,
25322,2,0,1,30,
2533158,18,1,30,159,
253420,160,4,22,68,
25350,101,0,99,0,
2536108,0,97,0,114,
25370,97,0,116,0,
2538105,0,111,0,110,
25390,1,118,1,2,
25402,0,1,31,161,
254118,1,31,162,20,
2542163,4,22,82,0,
254373,0,71,0,72,
25440,84,0,95,0,
254580,0,65,0,82,
25460,69,0,78,0,
25471,17,1,1,2,
25480,1,32,164,18,
25491,32,165,20,166,
25504,20,76,0,69,
25510,70,0,84,0,
255295,0,66,0,82,
25530,65,0,67,0,
255469,0,1,12,1,
25551,2,0,1,2650,
2556167,18,1,2650,168,
255720,169,4,44,73,
25580,110,0,116,0,
255982,0,111,0,116,
25600,82,0,111,0,
2561116,0,65,0,114,
25620,103,0,83,0,
2563116,0,97,0,116,
25640,101,0,69,0,
2565118,0,101,0,110,
25660,116,0,1,108,
25671,2,2,0,1,
25682819,170,18,1,2819,
2569171,20,172,4,34,
257071,0,108,0,111,
25710,98,0,97,0,
2572108,0,68,0,101,
25730,102,0,105,0,
2574110,0,105,0,116,
25750,105,0,111,0,
2576110,0,115,0,1,
257797,1,2,2,0,
25781,2652,173,18,1,
25792652,174,20,175,4,
258032,73,0,110,0,
2581116,0,65,0,114,
25820,103,0,83,0,
2583116,0,97,0,116,
25840,101,0,69,0,
2585118,0,101,0,110,
25860,116,0,1,106,
25871,2,2,0,1,
25881114,176,18,1,1114,
2589132,2,0,1,2654,
2590177,18,1,2654,153,
25912,0,1,1152,178,
259218,1,1152,179,20,
2593180,4,32,83,0,
2594105,0,109,0,112,
25950,108,0,101,0,
259665,0,115,0,115,
25970,105,0,103,0,
2598110,0,109,0,101,
25990,110,0,116,0,
26001,137,1,2,2,
26010,1,1117,181,18,
26021,1117,182,20,183,
26034,28,80,0,69,
26040,82,0,67,0,
260569,0,78,0,84,
26060,95,0,69,0,
260781,0,85,0,65,
26080,76,0,83,0,
26091,10,1,1,2,
26100,1,40,184,18,
26111,40,132,2,0,
26121,41,185,18,1,
261341,135,2,0,1,
261442,186,18,1,42,
2615187,20,188,4,20,
261669,0,120,0,112,
26170,114,0,101,0,
2618115,0,115,0,105,
26190,111,0,110,0,
26201,155,1,2,2,
26210,1,43,189,18,
26221,43,190,20,191,
26234,22,82,0,73,
26240,71,0,72,0,
262584,0,95,0,83,
26260,72,0,73,0,
262770,0,84,0,1,
262841,1,1,2,0,
26291,44,192,18,1,
263044,132,2,0,1,
26311159,193,18,1,1159,
2632187,2,0,1,46,
2633194,18,1,46,195,
263420,196,4,12,80,
26350,69,0,82,0,
263673,0,79,0,68,
26370,1,24,1,1,
26382,0,1,47,197,
263918,1,47,132,2,
26400,1,48,198,18,
26411,48,199,20,200,
26424,18,68,0,69,
26430,67,0,82,0,
264469,0,77,0,69,
26450,78,0,84,0,
26461,5,1,1,2,
26470,1,49,201,18,
26481,49,202,20,203,
26494,18,73,0,78,
26500,67,0,82,0,
265169,0,77,0,69,
26520,78,0,84,0,
26531,4,1,1,2,
26540,1,50,204,18,
26551,50,199,2,0,
26561,51,205,18,1,
265751,202,2,0,1,
265852,206,18,1,52,
2659135,2,0,1,2281,
2660207,18,1,2281,179,
26612,0,1,2839,208,
266218,1,2839,209,20,
2663210,4,48,71,0,
2664108,0,111,0,98,
26650,97,0,108,0,
266670,0,117,0,110,
26670,99,0,116,0,
2668105,0,111,0,110,
26690,68,0,101,0,
2670102,0,105,0,110,
26710,105,0,116,0,
2672105,0,111,0,110,
26730,1,99,1,2,
26742,0,1,2840,211,
267518,1,2840,212,20,
2676213,4,50,71,0,
2677108,0,111,0,98,
26780,97,0,108,0,
267986,0,97,0,114,
26800,105,0,97,0,
268198,0,108,0,101,
26820,68,0,101,0,
209599,0,108,0,97, 268399,0,108,0,97,
20960,114,0,97,0, 26840,114,0,97,0,
2097116,0,105,0,111, 2685116,0,105,0,111,
20980,110,0,1,105, 26860,110,0,1,98,
20991,2,2,0,1, 26871,2,2,0,1,
210031,152,18,1,31, 26882841,104,1,2842,214,
2101153,20,154,4,22, 268918,1,2842,215,23,
210282,0,73,0,71, 2690216,4,6,69,0,
21030,72,0,84,0, 269179,0,70,0,1,
210495,0,80,0,65, 26922,1,6,2,0,
21050,82,0,69,0, 26931,1730,217,18,1,
210678,0,1,17,1, 26941730,179,2,0,1,
21071,2,0,1,32, 26951731,218,18,1,1731,
2108155,18,1,32,156, 2696146,2,0,1,61,
210920,157,4,20,76, 2697219,18,1,61,129,
21100,69,0,70,0, 26982,0,1,62,220,
211184,0,95,0,66, 269918,1,62,162,2,
21120,82,0,65,0, 27000,1,63,221,18,
211367,0,69,0,1,
211412,1,1,2,0,
21151,1114,158,18,1,
21161114,132,2,0,1,
21171152,159,18,1,1152,
2118160,20,161,4,32,
211983,0,105,0,109,
21200,112,0,108,0,
2121101,0,65,0,115,
21220,115,0,105,0,
2123103,0,110,0,109,
21240,101,0,110,0,
2125116,0,1,113,1,
21262,2,0,1,1117,
2127162,18,1,1117,163,
212820,164,4,28,80,
21290,69,0,82,0,
213067,0,69,0,78,
21310,84,0,95,0,
213269,0,81,0,85,
21330,65,0,76,0,
213483,0,1,10,1,
21351,2,0,1,40,
2136165,18,1,40,132,
21372,0,1,41,166,
213818,1,41,135,2,
21390,1,42,167,18,
21401,42,168,20,169,
21414,20,69,0,120,
21420,112,0,114,0,
2143101,0,115,0,115,
21440,105,0,111,0,
2145110,0,1,131,1,
21462,2,0,1,43,
2147170,18,1,43,171,
214820,172,4,22,82,
21490,73,0,71,0,
215072,0,84,0,95,
21510,83,0,72,0,
215273,0,70,0,84,
21530,1,41,1,1,
21542,0,1,44,173,
215518,1,44,132,2,
21560,1,1159,174,18,
21571,1159,168,2,0,
21581,46,175,18,1,
215946,176,20,177,4,
216012,80,0,69,0,
216182,0,73,0,79,
21620,68,0,1,24,
21631,1,2,0,1,
216447,178,18,1,47,
2165132,2,0,1,48,
2166179,18,1,48,180,
216720,181,4,18,68,
21680,69,0,67,0,
216982,0,69,0,77,
21700,69,0,78,0,
217184,0,1,5,1,
21721,2,0,1,49,
2173182,18,1,49,183,
217420,184,4,18,73,
21750,78,0,67,0,
217682,0,69,0,77,
21770,69,0,78,0,
217884,0,1,4,1,
21791,2,0,1,50,
2180185,18,1,50,180,
21812,0,1,51,186,
218218,1,51,183,2,
21830,1,52,187,18,
21841,52,135,2,0,
21851,2281,188,18,1,
21862281,160,2,0,1,
21871730,189,18,1,1730,
2188160,2,0,1,1731,
2189190,18,1,1731,191,
219020,192,4,18,83,
21910,69,0,77,0,
219273,0,67,0,79,
21930,76,0,79,0,
219478,0,1,11,1,
21951,2,0,1,61,
2196193,18,1,61,129,
21972,0,1,62,194,
219818,1,62,153,2,
21990,1,63,195,18,
22001,63,132,2,0, 27011,63,132,2,0,
22011,65,196,18,1, 27021,65,222,18,1,
220265,176,2,0,1, 270365,195,2,0,1,
220366,197,18,1,66, 270466,223,18,1,66,
2204132,2,0,1,67, 2705132,2,0,1,67,
2205198,18,1,67,180, 2706224,18,1,67,199,
22062,0,1,68,199, 27072,0,1,68,225,
220718,1,68,183,2, 270818,1,68,202,2,
22080,1,69,200,18, 27090,1,69,226,18,
22091,69,180,2,0, 27101,69,199,2,0,
22101,70,201,18,1, 27111,70,227,18,1,
221170,183,2,0,1, 271270,202,2,0,1,
221271,202,18,1,71, 271371,228,18,1,71,
2213135,2,0,1,73, 2714135,2,0,1,73,
2214203,18,1,73,168, 2715229,18,1,73,187,
22152,0,1,74,204, 27162,0,1,74,230,
221618,1,74,153,2, 271718,1,74,162,2,
22170,1,1189,205,18, 27180,1,1189,231,18,
22181,1189,206,20,207, 27191,1189,232,20,233,
22194,22,83,0,84, 27204,22,83,0,84,
22200,65,0,82,0, 27210,65,0,82,0,
222195,0,69,0,81, 272295,0,69,0,81,
22220,85,0,65,0, 27230,85,0,65,0,
222376,0,83,0,1, 272476,0,83,0,1,
22248,1,1,2,0, 27258,1,1,2,0,
22251,76,208,18,1, 27261,76,234,18,1,
222676,209,20,210,4, 272776,235,20,236,4,
222720,76,0,69,0, 272820,76,0,69,0,
222870,0,84,0,95, 272970,0,84,0,95,
22290,83,0,72,0, 27300,83,0,72,0,
223073,0,70,0,84, 273173,0,70,0,84,
22310,1,40,1,1, 27320,1,40,1,1,
22322,0,1,1153,211, 27332,0,1,1153,237,
223318,1,1153,212,20, 273418,1,1153,238,20,
2234213,4,24,83,0, 2735239,4,24,83,0,
223576,0,65,0,83, 273676,0,65,0,83,
22360,72,0,95,0, 27370,72,0,95,0,
223769,0,81,0,85, 273869,0,81,0,85,
22380,65,0,76,0, 27390,65,0,76,0,
223983,0,1,9,1, 274083,0,1,9,1,
22401,2,0,1,79, 27411,2,0,1,79,
2241214,18,1,79,215, 2742240,18,1,79,241,
224220,216,4,10,84, 274320,242,4,10,84,
22430,73,0,76,0, 27440,73,0,76,0,
224468,0,69,0,1, 274568,0,69,0,1,
224536,1,1,2,0, 274636,1,1,2,0,
22461,1195,217,18,1, 27471,1195,243,18,1,
22471195,168,2,0,1, 27481195,187,2,0,1,
224882,218,18,1,82, 274982,244,18,1,82,
2249168,2,0,1,1123, 2750187,2,0,1,1123,
2250219,18,1,1123,168, 2751245,18,1,1123,187,
22512,0,1,85,220, 27522,0,1,85,246,
225218,1,85,221,20, 275318,1,85,247,20,
2253222,4,26,83,0, 2754248,4,26,83,0,
225484,0,82,0,79, 275584,0,82,0,79,
22550,75,0,69,0, 27560,75,0,69,0,
225695,0,83,0,84, 275795,0,83,0,84,
22570,82,0,79,0, 27580,82,0,79,0,
225875,0,69,0,1, 275975,0,69,0,1,
225939,1,1,2,0, 276039,1,1,2,0,
22601,89,223,18,1, 27611,2547,249,18,1,
226189,224,20,225,4, 27622547,250,20,251,4,
226210,77,0,73,0, 276364,73,0,110,0,
226378,0,85,0,83, 2764116,0,82,0,111,
22640,1,19,1,1, 27650,116,0,82,0,
22652,0,1,2318,226, 2766111,0,116,0,65,
226618,1,2318,191,2, 27670,114,0,103,0,
22670,1,93,227,18, 2768117,0,109,0,101,
22681,93,168,2,0, 27690,110,0,116,0,
22691,97,228,18,1, 277068,0,101,0,99,
227097,229,20,230,4, 27710,108,0,97,0,
2772114,0,97,0,116,
27730,105,0,111,0,
2774110,0,76,0,105,
27750,115,0,116,0,
27761,115,1,2,2,
27770,1,89,252,18,
27781,89,253,20,254,
27794,10,77,0,73,
27800,78,0,85,0,
278183,0,1,19,1,
27821,2,0,1,2318,
2783255,18,1,2318,146,
27842,0,1,2788,256,
278518,1,2788,187,2,
27860,1,93,257,18,
27871,93,187,2,0,
27881,97,258,18,1,
278997,259,20,260,4,
227114,65,0,77,0, 279014,65,0,77,0,
227280,0,95,0,65, 279180,0,95,0,65,
22730,77,0,80,0, 27920,77,0,80,0,
22741,38,1,1,2, 27931,38,1,1,2,
22750,1,102,231,18, 27940,1,102,261,18,
22761,102,232,20,233, 27951,102,262,20,263,
22774,22,69,0,88, 27964,22,69,0,88,
22780,67,0,76,0, 27970,67,0,76,0,
227965,0,77,0,65, 279865,0,77,0,65,
22800,84,0,73,0, 27990,84,0,73,0,
228179,0,78,0,1, 280079,0,78,0,1,
228237,1,1,2,0, 280137,1,1,2,0,
22831,1775,234,18,1, 28021,1775,264,18,1,
22841775,153,2,0,1, 28031775,162,2,0,1,
22852718,235,18,1,2718, 2804107,265,18,1,107,
2286236,23,237,4,6, 2805187,2,0,1,2337,
228769,0,79,0,70, 2806266,18,1,2337,162,
22880,1,2,1,6, 28072,0,1,1224,267,
22892,0,1,107,238, 280818,1,1224,179,2,
229018,1,107,168,2, 28090,1,1225,268,18,
22910,1,2337,239,18, 28101,1225,269,20,270,
22921,2337,153,2,0, 28114,24,77,0,73,
22931,1224,240,18,1, 28120,78,0,85,0,
22941224,160,2,0,1, 281383,0,95,0,69,
22951225,241,18,1,1225, 28140,81,0,85,0,
2296242,20,243,4,24, 281565,0,76,0,83,
229777,0,73,0,78, 28160,1,7,1,1,
22980,85,0,83,0, 28172,0,1,112,271,
229995,0,69,0,81, 281818,1,112,272,20,
23000,85,0,65,0, 2819273,4,28,71,0,
230176,0,83,0,1, 282082,0,69,0,65,
23027,1,1,2,0, 28210,84,0,69,0,
23031,112,244,18,1, 282282,0,95,0,69,
2304112,245,20,246,4, 28230,81,0,85,0,
230528,71,0,82,0, 282465,0,76,0,83,
230669,0,65,0,84, 28250,1,32,1,1,
23070,69,0,82,0, 28262,0,1,1188,274,
230895,0,69,0,81, 282718,1,1188,179,2,
23090,85,0,65,0, 28280,1,1231,275,18,
231076,0,83,0,1, 28291,1231,187,2,0,
231132,1,1,2,0, 28301,118,276,18,1,
23121,1188,247,18,1, 2831118,187,2,0,1,
23131188,160,2,0,1, 28321737,277,18,1,1737,
23141231,248,18,1,1231, 2833187,2,0,1,2818,
2315168,2,0,1,118, 2834278,18,1,2818,146,
2316249,18,1,118,168, 28352,0,1,124,279,
23172,0,1,1737,250, 283618,1,124,280,20,
231818,1,1737,168,2, 2837281,4,22,76,0,
23190,1,124,251,18, 283869,0,83,0,83,
23201,124,252,20,253, 28390,95,0,69,0,
23214,22,76,0,69, 284081,0,85,0,65,
23220,83,0,83,0, 28410,76,0,83,0,
232395,0,69,0,81, 28421,31,1,1,2,
23240,85,0,65,0, 28430,1,2657,282,18,
232576,0,83,0,1, 28441,2657,165,2,0,
232631,1,1,2,0, 28451,130,283,18,1,
23271,2657,254,18,1, 2846130,187,2,0,1,
23282657,150,2,0,1, 28471803,284,18,1,1803,
23292658,255,18,1,2658, 2848285,20,286,4,18,
2330256,20,257,4,12, 284983,0,116,0,97,
233169,0,81,0,85, 28500,116,0,101,0,
23320,65,0,76,0, 2851109,0,101,0,110,
233383,0,1,15,1, 28520,116,0,1,134,
23341,2,0,1,130, 28531,2,2,0,1,
2335258,18,1,130,168, 28541804,287,18,1,1804,
23362,0,1,1803,259, 2855288,20,289,4,4,
233718,1,1803,260,20, 285668,0,79,0,1,
2338261,4,18,83,0, 285744,1,1,2,0,
2339116,0,97,0,116, 28581,2830,290,18,1,
23400,101,0,109,0, 28592830,291,20,292,4,
2341101,0,110,0,116, 286012,83,0,116,0,
23420,1,110,1,2, 286197,0,116,0,101,
23432,0,1,1804,262, 28620,115,0,1,100,
234418,1,1804,263,20, 28631,2,2,0,1,
2345264,4,4,68,0, 28642364,293,18,1,2364,
234679,0,1,44,1, 2865285,2,0,1,137,
23471,2,0,1,2364, 2866294,18,1,137,295,
2348265,18,1,2364,260, 286720,296,4,36,69,
23492,0,1,137,266, 28680,88,0,67,0,
235018,1,137,267,20, 286976,0,65,0,77,
2351268,4,36,69,0, 28700,65,0,84,0,
235288,0,67,0,76, 287173,0,79,0,78,
23530,65,0,77,0, 28720,95,0,69,0,
235465,0,84,0,73, 287381,0,85,0,65,
23550,79,0,78,0, 28740,76,0,83,0,
235695,0,69,0,81, 28751,30,1,1,2,
23570,85,0,65,0, 28760,1,2293,297,18,
235876,0,83,0,1, 28771,2293,146,2,0,
235930,1,1,2,0, 28781,1701,298,18,1,
23601,2293,269,18,1, 28791701,187,2,0,1,
23612293,191,2,0,1, 28801756,299,18,1,1756,
23621701,270,18,1,1701, 2881146,2,0,1,2527,
2363168,2,0,1,1756, 2882300,18,1,2527,132,
2364271,18,1,1756,191, 28832,0,1,143,301,
23652,0,1,143,272, 288418,1,143,187,2,
236618,1,143,168,2, 28850,1,2299,302,18,
23670,1,2299,273,18, 28861,2299,187,2,0,
23681,2299,168,2,0, 28871,1260,303,18,1,
23691,1260,274,18,1, 28881260,179,2,0,1,
23701260,160,2,0,1, 28891261,304,18,1,1261,
23711261,275,18,1,1261, 2890305,20,306,4,22,
2372276,20,277,4,22,
237380,0,76,0,85, 289180,0,76,0,85,
23740,83,0,95,0, 28920,83,0,95,0,
237569,0,81,0,85, 289369,0,81,0,85,
23760,65,0,76,0, 28940,65,0,76,0,
237783,0,1,6,1, 289583,0,1,6,1,
23781,2,0,1,151, 28961,2,0,1,2528,
2379278,18,1,151,279, 2897307,18,1,2528,308,
238020,280,4,26,69, 289820,309,4,28,86,
28990,101,0,99,0,
290068,0,101,0,99,
29010,108,0,97,0,
2902114,0,97,0,116,
29030,105,0,111,0,
2904110,0,1,121,1,
29052,2,0,1,151,
2906310,18,1,151,311,
290720,312,4,26,69,
23810,81,0,85,0, 29080,81,0,85,0,
238265,0,76,0,83, 290965,0,76,0,83,
23830,95,0,69,0, 29100,95,0,69,0,
238481,0,85,0,65, 291181,0,85,0,65,
23850,76,0,83,0, 29120,76,0,83,0,
23861,29,1,1,2, 29131,29,1,1,2,
23870,1,1267,281,18, 29140,1,1267,313,18,
23881,1267,168,2,0, 29151,1267,187,2,0,
23891,157,282,18,1, 29161,2765,314,18,1,
2390157,168,2,0,1, 29172765,132,2,0,1,
23911773,283,18,1,1773, 2918157,315,18,1,157,
2392146,2,0,1,1832, 2919187,2,0,1,1773,
2393284,18,1,1832,260, 2920316,18,1,1773,149,
23942,0,1,1833,285, 29212,0,1,1832,317,
239518,1,1833,286,20, 292218,1,1832,285,2,
2396287,4,10,87,0, 29230,1,1833,318,18,
239772,0,73,0,76, 29241,1833,319,20,320,
23980,69,0,1,45, 29254,10,87,0,72,
29260,73,0,76,0,
292769,0,1,45,1,
29281,2,0,1,1834,
2929321,18,1,1834,135,
29302,0,1,166,322,
293118,1,166,323,20,
2932324,4,20,76,0,
293369,0,70,0,84,
29340,95,0,65,0,
293578,0,71,0,76,
29360,69,0,1,25,
23991,1,2,0,1, 29371,1,2,0,1,
24001834,288,18,1,1834, 29381840,325,18,1,1840,
2401135,2,0,1,166, 2939187,2,0,1,2779,
2402289,18,1,166,290, 2940326,18,1,2779,327,
240320,291,4,20,76, 294120,328,4,34,67,
24040,69,0,70,0, 29420,111,0,109,0,
240584,0,95,0,65, 2943112,0,111,0,117,
24060,78,0,71,0, 29440,110,0,100,0,
240776,0,69,0,1,
240825,1,1,2,0,
24091,1840,292,18,1,
24101840,168,2,0,1,
2411172,293,18,1,172,
2412168,2,0,1,2706,
2413294,18,1,2706,295,
241420,296,4,12,83,
24150,116,0,97,0,
2416116,0,101,0,115,
24170,1,100,1,2,
24182,0,1,2335,297,
241918,1,2335,146,2,
24200,1,1296,298,18,
24211,1296,160,2,0,
24221,1297,299,18,1,
24231297,256,2,0,1,
24242413,300,18,1,2413,
2425301,20,302,4,26,
242683,0,116,0,97, 294583,0,116,0,97,
24270,116,0,101,0, 29460,116,0,101,0,
2428109,0,101,0,110, 2947109,0,101,0,110,
24290,116,0,76,0, 29480,116,0,1,132,
2430105,0,115,0,116, 29491,2,2,0,1,
24310,1,109,1,2, 2950172,329,18,1,172,
24322,0,1,1859,303, 2951187,2,0,1,2335,
243318,1,1859,153,2, 2952330,18,1,2335,149,
24340,1,1860,304,18, 29532,0,1,1296,331,
24351,1860,191,2,0, 295418,1,1296,179,2,
24361,188,305,18,1, 29550,1,1297,332,18,
2437188,168,2,0,1, 29561,1297,333,20,334,
2438182,306,18,1,182, 29574,12,69,0,81,
2439307,20,308,4,22, 29580,85,0,65,0,
244082,0,73,0,71, 295976,0,83,0,1,
24410,72,0,84,0, 296015,1,1,2,0,
244295,0,65,0,78, 29611,2413,335,18,1,
24430,71,0,76,0, 29622413,336,20,337,4,
244469,0,1,26,1, 296326,83,0,116,0,
24451,2,0,1,199, 296497,0,116,0,101,
2446309,18,1,199,310, 29650,109,0,101,0,
244720,311,4,10,67, 2966110,0,116,0,76,
24480,65,0,82,0, 29670,105,0,115,0,
244969,0,84,0,1, 2968116,0,1,133,1,
245035,1,1,2,0, 29692,2,0,1,1859,
24511,1871,312,18,1, 2970338,18,1,1859,162,
24521871,160,2,0,1, 29712,0,1,1860,339,
24531872,313,18,1,1872, 297218,1,1860,146,2,
2454153,2,0,1,1873, 29730,1,188,340,18,
2455314,18,1,1873,191, 29741,188,187,2,0,
24562,0,1,1875,315, 29751,182,341,18,1,
245718,1,1875,286,2, 2976182,342,20,343,4,
24580,1,205,316,18, 297722,82,0,73,0,
24591,205,168,2,0, 297871,0,72,0,84,
24601,2515,317,18,1, 29790,95,0,65,0,
24612515,140,2,0,1, 298078,0,71,0,76,
24621882,318,18,1,1882, 29810,69,0,1,26,
2463168,2,0,1,2227, 29821,1,2,0,1,
2464319,18,1,2227,260, 2983199,344,18,1,199,
24652,0,1,217,320, 2984345,20,346,4,10,
246618,1,217,321,20, 298567,0,65,0,82,
2467322,4,12,83,0, 29860,69,0,84,0,
29871,35,1,1,2,
29880,1,1871,347,18,
29891,1871,179,2,0,
29901,1872,348,18,1,
29911872,162,2,0,1,
29921873,349,18,1,1873,
2993146,2,0,1,1875,
2994350,18,1,1875,319,
29952,0,1,205,351,
299618,1,205,187,2,
29970,1,2581,352,18,
29981,2581,135,2,0,
29991,1882,353,18,1,
30001882,187,2,0,1,
30012227,354,18,1,2227,
3002285,2,0,1,2590,
3003355,18,1,2590,140,
30042,0,1,217,356,
300518,1,217,357,20,
3006358,4,12,83,0,
246884,0,82,0,79, 300784,0,82,0,79,
24690,75,0,69,0, 30080,75,0,69,0,
24701,34,1,1,2, 30091,34,1,1,2,
24710,1,1332,323,18, 30100,1,1332,359,18,
24721,1332,160,2,0, 30111,1332,179,2,0,
24731,1335,324,18,1, 30121,1335,360,18,1,
24741335,163,2,0,1, 30131335,182,2,0,1,
2475223,325,18,1,223, 3014223,361,18,1,223,
2476168,2,0,1,1341, 3015187,2,0,1,1341,
2477326,18,1,1341,168, 3016362,18,1,1341,187,
24782,0,1,1901,327, 30172,0,1,1901,363,
247918,1,1901,153,2, 301818,1,1901,162,2,
24800,1,1303,328,18, 30190,1,1303,364,18,
24811,1303,168,2,0, 30201,1303,187,2,0,
24821,2462,329,18,1, 30211,2837,365,18,1,
24832462,260,2,0,1, 30222837,209,2,0,1,
2484236,330,18,1,236, 30232838,366,18,1,2838,
2485331,20,332,4,6, 3024212,2,0,1,2462,
248665,0,77,0,80, 3025367,18,1,2462,285,
24870,1,33,1,1, 30262,0,1,236,368,
24882,0,1,2466,333, 302718,1,236,369,20,
248918,1,2466,334,20, 3028370,4,6,65,0,
2490335,4,34,67,0, 302977,0,80,0,1,
2491111,0,109,0,112, 303033,1,1,2,0,
24920,111,0,117,0, 30311,2466,371,18,1,
2493110,0,100,0,83, 30322466,327,2,0,1,
24940,116,0,97,0, 30332467,372,18,1,2467,
2495116,0,101,0,109, 3034159,2,0,1,2468,
24960,101,0,110,0, 3035373,18,1,2468,374,
2497116,0,1,108,1, 303620,375,4,10,83,
24982,2,0,1,2467, 30370,84,0,65,0,
2499336,18,1,2467,150, 303884,0,69,0,1,
25002,0,1,2468,337, 303948,1,1,2,0,
250118,1,2468,338,20, 30401,2469,376,18,1,
2502339,4,10,83,0, 30412469,132,2,0,1,
250384,0,65,0,84, 3042242,377,18,1,242,
25040,69,0,1,48, 3043187,2,0,1,2471,
25051,1,2,0,1, 3044378,18,1,2471,379,
25062469,340,18,1,2469, 304520,380,4,26,67,
2507132,2,0,1,242, 30460,79,0,78,0,
2508341,18,1,242,168, 304784,0,82,0,79,
25092,0,1,2471,342, 30480,76,0,95,0,
251018,1,2471,343,20,
2511344,4,36,72,0,
251284,0,84,0,80,
25130,95,0,82,0,
251469,0,81,0,85,
25150,69,0,83,0,
251684,0,95,0,69,
25170,86,0,69,0,
251878,0,84,0,1,
251991,1,1,2,0,
25201,2472,345,18,1,
25212472,346,20,347,4,
252234,84,0,79,0,
252385,0,67,0,72,
25240,95,0,83,0,
252584,0,65,0,82,
25260,84,0,95,0,
252769,0,86,0,69, 304969,0,86,0,69,
25280,78,0,84,0, 30500,78,0,84,0,
25291,89,1,1,2, 30511,65,1,1,2,
25300,1,2473,348,18, 30520,1,2472,381,18,
25311,2473,349,20,350, 30531,2472,382,20,383,
25324,30,84,0,79, 30544,30,65,0,84,
25330,85,0,67,0, 30550,95,0,84,0,
253472,0,95,0,69, 305665,0,82,0,71,
25350,78,0,68,0, 30570,69,0,84,0,
305895,0,69,0,86,
30590,69,0,78,0,
306084,0,1,59,1,
30611,2,0,1,2473,
3062384,18,1,2473,385,
306320,386,4,38,65,
30640,84,0,95,0,
306582,0,79,0,84,
30660,95,0,84,0,
306765,0,82,0,71,
30680,69,0,84,0,
253695,0,69,0,86, 306995,0,69,0,86,
25370,69,0,78,0, 30700,69,0,78,0,
253884,0,1,90,1, 307184,0,1,58,1,
25391,2,0,1,2474, 30721,2,0,1,2474,
2540351,18,1,2474,352, 3073387,18,1,2474,388,
254120,353,4,22,84, 307420,389,4,52,76,
25420,79,0,85,0, 30750,65,0,78,0,
254367,0,72,0,95, 307668,0,95,0,67,
30770,79,0,76,0,
307876,0,73,0,83,
30790,73,0,79,0,
308078,0,95,0,83,
30810,84,0,65,0,
308282,0,84,0,95,
25440,69,0,86,0, 30830,69,0,86,0,
254569,0,78,0,84, 308469,0,78,0,84,
25460,1,88,1,1, 30850,1,71,1,1,
25472,0,1,2475,354, 30862,0,1,2475,390,
254818,1,2475,355,20, 308718,1,2475,391,20,
2549356,4,22,84,0, 3088392,4,48,76,0,
255073,0,77,0,69, 308965,0,78,0,68,
25510,82,0,95,0, 30900,95,0,67,0,
255269,0,86,0,69, 309179,0,76,0,76,
25530,78,0,84,0, 30920,73,0,83,0,
25541,87,1,1,2, 309373,0,79,0,78,
25550,1,2476,357,18, 30940,95,0,69,0,
25561,2476,358,20,359, 309578,0,68,0,95,
25574,32,83,0,84, 30960,69,0,86,0,
25580,65,0,84,0, 309769,0,78,0,84,
255969,0,95,0,69, 30980,1,70,1,1,
25600,88,0,73,0, 30992,0,1,2476,393,
310018,1,2476,394,20,
3101395,4,40,76,0,
310265,0,78,0,68,
31030,95,0,67,0,
310479,0,76,0,76,
31050,73,0,83,0,
310673,0,79,0,78,
31070,95,0,69,0,
310886,0,69,0,78,
31090,84,0,1,69,
31101,1,2,0,1,
31112477,396,18,1,2477,
3112397,20,398,4,34,
311384,0,79,0,85,
31140,67,0,72,0,
311595,0,83,0,84,
31160,65,0,82,0,
256184,0,95,0,69, 311784,0,95,0,69,
25620,86,0,69,0, 31180,86,0,69,0,
256378,0,84,0,1, 311978,0,84,0,1,
256486,1,1,2,0, 312089,1,1,2,0,
25651,2477,360,18,1, 31211,2478,399,18,1,
25662477,361,20,362,4, 31222478,400,20,401,4,
256734,83,0,84,0, 312330,84,0,79,0,
256865,0,84,0,69, 312485,0,67,0,72,
25690,95,0,69,0, 31250,95,0,69,0,
257078,0,84,0,82, 312678,0,68,0,95,
25710,89,0,95,0, 31270,69,0,86,0,
312869,0,78,0,84,
31290,1,90,1,1,
31302,0,1,2479,402,
313118,1,2479,403,20,
3132404,4,22,84,0,
313379,0,85,0,67,
31340,72,0,95,0,
257269,0,86,0,69, 313569,0,86,0,69,
25730,78,0,84,0, 31360,78,0,84,0,
25741,85,1,1,2, 31371,88,1,1,2,
25750,1,2478,363,18, 31380,1,2480,405,18,
25761,2478,364,20,365, 31391,2480,406,20,407,
25774,24,83,0,69, 31404,24,83,0,69,
25780,78,0,83,0, 31410,78,0,83,0,
257979,0,82,0,95, 314279,0,82,0,95,
25800,69,0,86,0, 31430,69,0,86,0,
258169,0,78,0,84, 314469,0,78,0,84,
25820,1,84,1,1, 31450,1,84,1,1,
25832,0,1,2479,366, 31462,0,1,2481,408,
258418,1,2479,367,20, 314718,1,2481,409,20,
2585368,4,52,82,0, 3148410,4,52,82,0,
258685,0,78,0,95, 314985,0,78,0,95,
25870,84,0,73,0, 31500,84,0,73,0,
258877,0,69,0,95, 315177,0,69,0,95,
@@ -2594,291 +3157,125 @@ public yyLSLSyntax
259469,0,86,0,69, 315769,0,86,0,69,
25950,78,0,84,0, 31580,78,0,84,0,
25961,83,1,1,2, 31591,83,1,1,2,
25970,1,2480,369,18, 31600,1,2482,411,18,
25981,2480,370,20,371, 31611,2482,412,20,413,
25994,34,82,0,69, 31624,24,79,0,78,
26000,77,0,79,0,
260184,0,69,0,95,
26020,68,0,65,0,
260384,0,65,0,95,
26040,69,0,86,0,
260569,0,78,0,84,
26060,1,82,1,1,
26072,0,1,2481,372,
260818,1,2481,373,20,
2609374,4,24,79,0,
261078,0,95,0,82,
26110,69,0,90,0,
261295,0,69,0,86,
26130,69,0,78,0,
261484,0,1,81,1,
26151,2,0,1,2482,
2616375,18,1,2482,376,
261720,377,4,32,79,
26180,66,0,74,0,
261969,0,67,0,84,
26200,95,0,82,0, 31630,95,0,82,0,
262169,0,90,0,95, 316469,0,90,0,95,
26220,69,0,86,0, 31650,69,0,86,0,
262369,0,78,0,84, 316669,0,78,0,84,
26240,1,80,1,1, 31670,1,81,1,1,
26252,0,1,2483,378, 31682,0,1,2483,414,
262618,1,2483,379,20, 316918,1,2483,415,20,
2627380,4,38,78,0, 3170416,4,42,67,0,
262879,0,84,0,95,
26290,65,0,84,0,
263095,0,84,0,65,
26310,82,0,71,0,
263269,0,84,0,95,
26330,69,0,86,0,
263469,0,78,0,84,
26350,1,79,1,1,
26362,0,1,256,381,
263718,1,256,382,20,
2638383,4,14,80,0,
263969,0,82,0,67,
26400,69,0,78,0,
264184,0,1,22,1,
26421,2,0,1,1371,
2643384,18,1,1371,212,
26442,0,1,2486,385,
264518,1,2486,386,20,
2646387,4,36,77,0,
264779,0,86,0,73,
26480,78,0,71,0,
264995,0,83,0,84,
26500,65,0,82,0,
265184,0,95,0,69,
26520,86,0,69,0,
265378,0,84,0,1,
265476,1,1,2,0,
26551,2487,388,18,1,
26562487,389,20,390,4,
265732,77,0,79,0,
265886,0,73,0,78,
26590,71,0,95,0,
266069,0,78,0,68,
26610,95,0,69,0,
266286,0,69,0,78,
26630,84,0,1,75,
26641,1,2,0,1,
26651931,391,18,1,1931,
2666260,2,0,1,1932,
2667392,18,1,1932,393,
266820,394,4,4,73,
26690,70,0,1,42,
26701,1,2,0,1,
2671262,395,18,1,262,
2672168,2,0,1,1377,
2673396,18,1,1377,168,
26742,0,1,2492,397,
267518,1,2492,398,20,
2676399,4,48,76,0,
267765,0,78,0,68,
26780,95,0,67,0,
267979,0,76,0,76, 317179,0,76,0,76,
26800,73,0,83,0, 31720,73,0,83,0,
268173,0,79,0,78, 317373,0,79,0,78,
26820,95,0,69,0, 31740,95,0,83,0,
268378,0,68,0,95, 317584,0,65,0,82,
26840,69,0,86,0, 31760,84,0,95,0,
268569,0,78,0,84,
26860,1,70,1,1,
26872,0,1,1876,400,
268818,1,1876,135,2,
26890,1,2494,401,18,
26901,2494,402,20,403,
26914,38,72,0,84,
26920,84,0,80,0,
269395,0,82,0,69,
26940,83,0,80,0,
269579,0,78,0,83,
26960,69,0,95,0,
269769,0,86,0,69, 317769,0,86,0,69,
26980,78,0,84,0, 31780,78,0,84,0,
26991,68,1,1,2, 31791,64,1,1,2,
27000,1,2495,404,18, 31800,1,256,417,18,
27011,2495,405,20,406, 31811,256,418,20,419,
27024,22,69,0,77, 31824,14,80,0,69,
27030,65,0,73,0, 31830,82,0,67,0,
270476,0,95,0,69,
27050,86,0,69,0,
270678,0,84,0,1,
270767,1,1,2,0,
27081,1939,407,18,1,
27091939,168,2,0,1,
27102497,408,18,1,2497,
2711409,20,410,4,26,
271267,0,79,0,78,
27130,84,0,82,0,
271479,0,76,0,95,
27150,69,0,86,0,
271669,0,78,0,84, 318469,0,78,0,84,
27170,1,65,1,1, 31850,1,22,1,1,
27182,0,1,827,411, 31862,0,1,1371,420,
271918,1,827,168,2, 318718,1,1371,238,2,
27200,1,2499,412,18, 31880,1,2486,421,18,
27211,2499,413,20,414, 31891,2486,422,20,423,
27224,38,67,0,79, 31904,26,67,0,72,
27230,76,0,76,0, 31910,65,0,78,0,
272473,0,83,0,73, 319271,0,69,0,68,
27250,79,0,78,0, 31930,95,0,69,0,
272695,0,69,0,78, 319486,0,69,0,78,
27270,68,0,95,0, 31950,84,0,1,61,
272869,0,86,0,69, 31961,1,2,0,1,
27290,78,0,84,0, 31972487,424,18,1,2487,
27301,63,1,1,2, 3198425,20,426,4,32,
27310,1,2500,415,18, 319979,0,66,0,74,
27321,2500,416,20,417, 32000,69,0,67,0,
27334,30,67,0,79, 320184,0,95,0,82,
27340,76,0,76,0, 32020,69,0,90,0,
273573,0,83,0,73, 320395,0,69,0,86,
27360,79,0,78,0, 32040,69,0,78,0,
320584,0,1,80,1,
32061,2,0,1,1931,
3207427,18,1,1931,285,
32082,0,1,1932,428,
320918,1,1932,429,20,
3210430,4,4,73,0,
321170,0,1,42,1,
32121,2,0,1,262,
3213431,18,1,262,187,
32142,0,1,1377,432,
321518,1,1377,187,2,
32160,1,2492,433,18,
32171,2492,434,20,435,
32184,30,78,0,79,
32190,95,0,83,0,
322069,0,78,0,83,
32210,79,0,82,0,
273795,0,69,0,86, 322295,0,69,0,86,
27380,69,0,78,0, 32230,69,0,78,0,
273984,0,1,62,1, 322484,0,1,77,1,
27401,2,0,1,2501, 32251,2,0,1,1876,
2741418,18,1,2501,419, 3226436,18,1,1876,135,
274220,420,4,26,67, 32272,0,1,2494,437,
27430,72,0,65,0, 322818,1,2494,438,20,
274478,0,71,0,69, 3229439,4,32,77,0,
323079,0,86,0,73,
32310,78,0,71,0,
323295,0,69,0,78,
27450,68,0,95,0, 32330,68,0,95,0,
274669,0,86,0,69, 323469,0,86,0,69,
27470,78,0,84,0, 32350,78,0,84,0,
27481,61,1,1,2, 32361,75,1,1,2,
27490,1,2502,421,18, 32370,1,2495,440,18,
27501,2502,422,20,423, 32381,2495,441,20,442,
27514,24,65,0,84, 32394,32,83,0,84,
27520,84,0,65,0, 32400,65,0,84,0,
275367,0,72,0,95, 324169,0,95,0,69,
32420,88,0,73,0,
324384,0,95,0,69,
32440,86,0,69,0,
324578,0,84,0,1,
324686,1,1,2,0,
32471,1939,443,18,1,
32481939,187,2,0,1,
32492497,444,18,1,2497,
3250445,20,446,4,36,
325172,0,84,0,84,
32520,80,0,95,0,
325382,0,69,0,81,
32540,85,0,69,0,
325583,0,84,0,95,
27540,69,0,86,0, 32560,69,0,86,0,
275569,0,78,0,84, 325769,0,78,0,84,
27560,1,60,1,1, 32580,1,91,1,1,
27572,0,1,2503,424, 32592,0,1,827,447,
275818,1,2503,425,20, 326018,1,827,187,2,
2759426,4,30,65,0, 32610,1,2499,448,18,
276084,0,95,0,84, 32621,2499,449,20,450,
27610,65,0,82,0,
276271,0,69,0,84,
27630,95,0,69,0,
276486,0,69,0,78,
27650,84,0,1,59,
27661,1,2,0,1,
27672504,427,18,1,2504,
2768428,20,429,4,38,
276965,0,84,0,95,
27700,82,0,79,0,
277184,0,95,0,84,
27720,65,0,82,0,
277371,0,69,0,84,
27740,95,0,69,0,
277586,0,69,0,78,
27760,84,0,1,58,
27771,1,2,0,1,
2778277,430,18,1,277,
2779431,20,432,4,10,
278083,0,76,0,65,
27810,83,0,72,0,
27821,21,1,1,2,
27830,1,2506,433,18,
27841,2506,135,2,0,
27851,283,434,18,1,
2786283,168,2,0,1,
27871958,435,18,1,1958,
2788153,2,0,1,2517,
2789436,18,1,2517,153,
27902,0,1,2519,437,
279118,1,2519,334,2,
27920,1,1406,438,18,
27931,1406,160,2,0,
27941,1407,439,18,1,
27951407,206,2,0,1,
2796299,440,18,1,299,
2797441,20,442,4,8,
279883,0,84,0,65,
27990,82,0,1,20,
28001,1,2,0,1,
28011370,443,18,1,1370,
2802160,2,0,1,305,
2803444,18,1,305,168,
28042,0,1,2458,445,
280518,1,2458,260,2,
28060,1,2459,446,18,
28071,2459,447,20,448,
28084,22,82,0,73,
28090,71,0,72,0,
281084,0,95,0,66,
28110,82,0,65,0,
281267,0,69,0,1,
281313,1,1,2,0,
28141,2464,449,18,1,
28152464,447,2,0,1,
28161989,450,18,1,1989,
2817260,2,0,1,1990,
2818451,18,1,1990,452,
281920,453,4,8,69,
28200,76,0,83,0,
282169,0,1,43,1,
28221,2,0,1,2470,
2823454,18,1,2470,156,
28242,0,1,322,455,
282518,1,322,224,2,
28260,1,1933,456,18,
28271,1933,135,2,0,
28281,883,457,18,1,
2829883,168,2,0,1,
2830328,458,18,1,328,
2831168,2,0,1,1443,
2832459,18,1,1443,242,
28332,0,1,2558,460,
283418,1,2558,447,2,
28350,1,2559,461,18,
28361,2559,462,20,463,
28374,20,83,0,116,
28380,97,0,116,0,
2839101,0,69,0,118,
28400,101,0,110,0,
2841116,0,1,103,1,
28422,2,0,1,2560,
2843464,18,1,2560,465,
284420,466,4,26,68,
28450,69,0,70,0,
284665,0,85,0,76,
28470,84,0,95,0,
284883,0,84,0,65,
28490,84,0,69,0,
28501,47,1,1,2,
28510,1,2561,467,18,
28521,2561,156,2,0,
28531,1449,468,18,1,
28541449,168,2,0,1,
28552485,469,18,1,2485,
2856470,20,471,4,30,
285778,0,79,0,95,
28580,83,0,69,0,
285978,0,83,0,79,
28600,82,0,95,0,
286169,0,86,0,69,
28620,78,0,84,0,
28631,77,1,1,2,
28640,1,2488,472,18,
28651,2488,473,20,474,
28664,22,77,0,79, 32634,22,77,0,79,
28670,78,0,69,0, 32640,78,0,69,0,
286889,0,95,0,69, 326589,0,95,0,69,
28690,86,0,69,0, 32660,86,0,69,0,
287078,0,84,0,1, 326778,0,84,0,1,
287174,1,1,2,0, 326874,1,1,2,0,
28721,2489,475,18,1, 32691,2500,451,18,1,
28732489,476,20,477,4, 32702500,452,20,453,4,
287424,76,0,73,0, 327124,76,0,73,0,
287583,0,84,0,69, 327283,0,84,0,69,
28760,78,0,95,0, 32730,78,0,95,0,
287769,0,86,0,69, 327469,0,86,0,69,
28780,78,0,84,0, 32750,78,0,84,0,
28791,73,1,1,2, 32761,73,1,1,2,
28800,1,2490,478,18, 32770,1,2501,454,18,
28811,2490,479,20,480, 32781,2501,455,20,456,
28824,36,76,0,73, 32794,36,76,0,73,
28830,78,0,75,0, 32800,78,0,75,0,
288495,0,77,0,69, 328195,0,77,0,69,
@@ -2888,480 +3285,889 @@ public yyLSLSyntax
288886,0,69,0,78, 328586,0,69,0,78,
28890,84,0,1,72, 32860,84,0,1,72,
28901,1,2,0,1, 32871,1,2,0,1,
28912491,481,18,1,2491, 32882502,457,18,1,2502,
2892482,20,483,4,52, 3289458,20,459,4,38,
289376,0,65,0,78, 329072,0,84,0,84,
28940,68,0,95,0, 32910,80,0,95,0,
329282,0,69,0,83,
32930,80,0,79,0,
329478,0,83,0,69,
32950,95,0,69,0,
329686,0,69,0,78,
32970,84,0,1,68,
32981,1,2,0,1,
32992503,460,18,1,2503,
3300461,20,462,4,22,
330169,0,77,0,65,
33020,73,0,76,0,
330395,0,69,0,86,
33040,69,0,78,0,
330584,0,1,67,1,
33061,2,0,1,2504,
3307463,18,1,2504,464,
330820,465,4,32,68,
33090,65,0,84,0,
331065,0,83,0,69,
33110,82,0,86,0,
331269,0,82,0,95,
33130,69,0,86,0,
331469,0,78,0,84,
33150,1,66,1,1,
33162,0,1,277,466,
331718,1,277,467,20,
3318468,4,10,83,0,
331976,0,65,0,83,
33200,72,0,1,21,
33211,1,2,0,1,
33222506,469,18,1,2506,
3323135,2,0,1,2507,
3324470,18,1,2507,117,
33252,0,1,2508,471,
332618,1,2508,132,2,
33270,1,2509,472,18,
33281,2509,473,20,474,
33294,28,75,0,101,
33300,121,0,68,0,
3331101,0,99,0,108,
33320,97,0,114,0,
333397,0,116,0,105,
33340,111,0,110,0,
33351,119,1,2,2,
33360,1,2510,475,18,
33371,2510,143,2,0,
33381,283,476,18,1,
3339283,187,2,0,1,
33402512,477,18,1,2512,
3341132,2,0,1,2513,
3342478,18,1,2513,479,
334320,480,4,28,73,
33440,110,0,116,0,
334568,0,101,0,99,
33460,108,0,97,0,
3347114,0,97,0,116,
33480,105,0,111,0,
3349110,0,1,120,1,
33502,2,0,1,2514,
3351481,18,1,2514,143,
33522,0,1,1958,482,
335318,1,1958,162,2,
33540,1,2516,483,18,
33551,2516,479,2,0,
33561,2517,484,18,1,
33572517,485,20,486,4,
335864,75,0,101,0,
3359121,0,73,0,110,
33600,116,0,73,0,
3361110,0,116,0,65,
33620,114,0,103,0,
3363117,0,109,0,101,
33640,110,0,116,0,
336568,0,101,0,99,
33660,108,0,97,0,
3367114,0,97,0,116,
33680,105,0,111,0,
3369110,0,76,0,105,
33700,115,0,116,0,
33711,117,1,2,2,
33720,1,2518,487,18,
33731,2518,162,2,0,
33741,1406,488,18,1,
33751406,179,2,0,1,
33761407,489,18,1,1407,
3377232,2,0,1,2522,
3378490,18,1,2522,135,
33792,0,1,2524,491,
338018,1,2524,479,2,
33810,1,2525,492,18,
33821,2525,143,2,0,
33831,2526,493,18,1,
33842526,114,2,0,1,
3385299,494,18,1,299,
3386495,20,496,4,8,
338783,0,84,0,65,
33880,82,0,1,20,
33891,1,2,0,1,
33901370,497,18,1,1370,
3391179,2,0,1,2529,
3392498,18,1,2529,143,
33932,0,1,2531,499,
339418,1,2531,308,2,
33950,1,2532,500,18,
33961,2532,501,20,502,
33974,64,73,0,110,
33980,116,0,86,0,
3399101,0,99,0,86,
34000,101,0,99,0,
340165,0,114,0,103,
34020,117,0,109,0,
3403101,0,110,0,116,
34040,68,0,101,0,
340599,0,108,0,97,
34060,114,0,97,0,
3407116,0,105,0,111,
34080,110,0,76,0,
3409105,0,115,0,116,
34100,1,116,1,2,
34112,0,1,305,503,
341218,1,305,187,2,
34130,1,2535,504,18,
34141,2535,327,2,0,
34151,2458,505,18,1,
34162458,285,2,0,1,
34172459,506,18,1,2459,
3418507,20,508,4,22,
341982,0,73,0,71,
34200,72,0,84,0,
342195,0,66,0,82,
34220,65,0,67,0,
342369,0,1,13,1,
34241,2,0,1,2539,
3425509,18,1,2539,479,
34262,0,1,2540,510,
342718,1,2540,143,2,
34280,1,2541,511,18,
34291,2541,111,2,0,
34301,2542,512,18,1,
34312542,132,2,0,1,
34322464,513,18,1,2464,
3433507,2,0,1,2544,
3434514,18,1,2544,143,
34352,0,1,1989,515,
343618,1,1989,285,2,
34370,1,1990,516,18,
34381,1990,517,20,518,
34394,8,69,0,76,
34400,83,0,69,0,
34411,43,1,1,2,
34420,1,2548,519,18,
34431,2548,162,2,0,
34441,2470,520,18,1,
34452470,165,2,0,1,
3446322,521,18,1,322,
3447253,2,0,1,2551,
3448522,18,1,2551,523,
344920,524,4,28,86,
34500,101,0,99,0,
3451116,0,111,0,114,
34520,65,0,114,0,
3453103,0,69,0,118,
34540,101,0,110,0,
3455116,0,1,128,1,
34562,2,0,1,1933,
3457525,18,1,1933,135,
34582,0,1,883,526,
345918,1,883,187,2,
34600,1,2555,527,18,
34611,2555,528,20,529,
34624,58,86,0,101,
34630,99,0,116,0,
3464111,0,114,0,65,
34650,114,0,103,0,
3466117,0,109,0,101,
34670,110,0,116,0,
346868,0,101,0,99,
34690,108,0,97,0,
3470114,0,97,0,116,
34710,105,0,111,0,
3472110,0,76,0,105,
34730,115,0,116,0,
34741,114,1,2,2,
34750,1,328,530,18,
34761,328,187,2,0,
34771,1443,531,18,1,
34781443,269,2,0,1,
34792558,532,18,1,2558,
3480327,2,0,1,2559,
3481533,18,1,2559,534,
348220,535,4,22,73,
34830,110,0,116,0,
348465,0,114,0,103,
34850,69,0,118,0,
3486101,0,110,0,116,
34870,1,127,1,2,
34882,0,1,2560,536,
348918,1,2560,135,2,
34900,1,2562,537,18,
34911,2562,479,2,0,
34921,1449,538,18,1,
34931449,187,2,0,1,
34942485,539,18,1,2485,
3495540,20,541,4,30,
289567,0,79,0,76, 349667,0,79,0,76,
28960,76,0,73,0, 34970,76,0,73,0,
289783,0,73,0,79, 349883,0,73,0,79,
28980,78,0,95,0, 34990,78,0,95,0,
289983,0,84,0,65, 350069,0,86,0,69,
29000,82,0,84,0, 35010,78,0,84,0,
35021,62,1,1,2,
35030,1,2566,542,18,
35041,2566,327,2,0,
35051,2488,543,18,1,
35062488,544,20,545,4,
350724,65,0,84,0,
350884,0,65,0,67,
35090,72,0,95,0,
351069,0,86,0,69,
35110,78,0,84,0,
35121,60,1,1,2,
35130,1,2489,546,18,
35141,2489,547,20,548,
35154,22,84,0,73,
35160,77,0,69,0,
351782,0,95,0,69,
35180,86,0,69,0,
351978,0,84,0,1,
352087,1,1,2,0,
35211,2490,549,18,1,
35222490,550,20,551,4,
352338,78,0,79,0,
352484,0,95,0,65,
35250,84,0,95,0,
352684,0,65,0,82,
35270,71,0,69,0,
352884,0,95,0,69,
35290,86,0,69,0,
353078,0,84,0,1,
353179,1,1,2,0,
35321,2491,552,18,1,
35332491,553,20,554,4,
353446,78,0,79,0,
353584,0,95,0,65,
35360,84,0,95,0,
353782,0,79,0,84,
35380,95,0,84,0,
353965,0,82,0,71,
35400,69,0,84,0,
290195,0,69,0,86, 354195,0,69,0,86,
29020,69,0,78,0, 35420,69,0,78,0,
290384,0,1,71,1, 354384,0,1,78,1,
29041,2,0,1,2493, 35441,2,0,1,2571,
2905484,18,1,2493,485, 3545555,18,1,2571,556,
290620,486,4,40,76, 354620,557,4,52,75,
29070,65,0,78,0, 35470,101,0,121,0,
290868,0,95,0,67, 354865,0,114,0,103,
29090,79,0,76,0, 35490,117,0,109,0,
291076,0,73,0,83, 3550101,0,110,0,116,
29110,73,0,79,0, 35510,68,0,101,0,
291278,0,95,0,69, 355299,0,108,0,97,
35530,114,0,97,0,
3554116,0,105,0,111,
35550,110,0,76,0,
3556105,0,115,0,116,
35570,1,112,1,2,
35582,0,1,2493,558,
355918,1,2493,559,20,
3560560,4,36,77,0,
356179,0,86,0,73,
35620,78,0,71,0,
356395,0,83,0,84,
35640,65,0,82,0,
356584,0,95,0,69,
29130,86,0,69,0, 35660,86,0,69,0,
291478,0,84,0,1, 356778,0,84,0,1,
291569,1,1,2,0, 356876,1,1,2,0,
29161,1413,487,18,1, 35691,1413,561,18,1,
29171413,168,2,0,1, 35701413,187,2,0,1,
2918346,488,18,1,346, 3571346,562,18,1,346,
2919489,20,490,4,8, 3572563,20,564,4,8,
292080,0,76,0,85, 357380,0,76,0,85,
29210,83,0,1,18, 35740,83,0,1,18,
29221,1,2,0,1, 35751,1,2,0,1,
29232496,491,18,1,2496, 35762575,565,18,1,2575,
2924492,20,493,4,32, 3577566,20,567,4,24,
292568,0,65,0,84, 357886,0,111,0,105,
29260,65,0,83,0, 35790,100,0,65,0,
292769,0,82,0,86, 3580114,0,103,0,69,
29280,69,0,82,0, 35810,118,0,101,0,
292995,0,69,0,86, 3582110,0,116,0,1,
29300,69,0,78,0, 3583125,1,2,2,0,
293184,0,1,66,1, 35841,2496,568,18,1,
29321,2,0,1,2021, 35852496,569,20,570,4,
2933494,18,1,2021,260, 358634,83,0,84,0,
29342,0,1,2022,495, 358765,0,84,0,69,
293518,1,2022,338,2, 35880,95,0,69,0,
29360,1,352,496,18, 358978,0,84,0,82,
29371,352,168,2,0, 35900,89,0,95,0,
29381,2024,497,18,1, 359169,0,86,0,69,
29392024,132,2,0,1, 35920,78,0,84,0,
29402025,498,18,1,2025, 35931,85,1,1,2,
2941499,20,500,4,8, 35940,1,2577,571,18,
294274,0,85,0,77, 35951,2577,162,2,0,
29430,80,0,1,49, 35961,2021,572,18,1,
29441,1,2,0,1, 35972021,285,2,0,1,
29452026,501,18,1,2026, 35982022,573,18,1,2022,
2946132,2,0,1,2027, 3599374,2,0,1,352,
2947502,18,1,2027,503, 3600574,18,1,352,187,
294820,504,4,4,65, 36012,0,1,2024,575,
29490,84,0,1,23, 360218,1,2024,132,2,
29501,1,2,0,1, 36030,1,2025,576,18,
29512028,505,18,1,2028, 36041,2025,577,20,578,
2952132,2,0,1,2029, 36054,8,74,0,85,
2953506,18,1,2029,334, 36060,77,0,80,0,
29542,0,1,2030,507, 36071,49,1,1,2,
295518,1,2030,508,20, 36080,1,2026,579,18,
2956509,4,14,70,0, 36091,2026,132,2,0,
2957111,0,114,0,76, 36101,2027,580,18,1,
29580,111,0,111,0, 36112027,581,20,582,4,
2959112,0,1,121,1, 36124,65,0,84,0,
29602,2,0,1,2031, 36131,23,1,1,2,
2961510,18,1,2031,511, 36140,1,2028,583,18,
296220,512,4,32,68, 36151,2028,132,2,0,
29630,111,0,87,0, 36161,2029,584,18,1,
2964104,0,105,0,108, 36172029,327,2,0,1,
29650,101,0,83,0, 36182030,585,18,1,2030,
2966116,0,97,0,116, 3619586,20,587,4,14,
29670,101,0,109,0, 362070,0,111,0,114,
2968101,0,110,0,116, 36210,76,0,111,0,
29690,1,120,1,2, 3622111,0,112,0,1,
29702,0,1,2032,513, 3623145,1,2,2,0,
297118,1,2032,514,20, 36241,2031,588,18,1,
2972515,4,28,87,0, 36252031,589,20,590,4,
2973104,0,105,0,108, 362632,68,0,111,0,
29740,101,0,83,0, 362787,0,104,0,105,
2975116,0,97,0,116, 36280,108,0,101,0,
29760,101,0,109,0, 362983,0,116,0,97,
2977101,0,110,0,116, 36300,116,0,101,0,
29780,1,119,1,2, 3631109,0,101,0,110,
29792,0,1,2033,516, 36320,116,0,1,144,
298018,1,2033,517,20, 36331,2,2,0,1,
2981518,4,22,73,0, 36342032,591,18,1,2032,
2982102,0,83,0,116, 3635592,20,593,4,28,
29830,97,0,116,0, 363687,0,104,0,105,
2984101,0,109,0,101, 36370,108,0,101,0,
29850,110,0,116,0, 363883,0,116,0,97,
29861,118,1,2,2, 36390,116,0,101,0,
29870,1,2034,519,18, 3640109,0,101,0,110,
29881,2034,520,20,521, 36410,116,0,1,143,
29894,22,83,0,116, 36421,2,2,0,1,
29900,97,0,116,0, 36432033,594,18,1,2033,
2991101,0,67,0,104, 3644595,20,596,4,22,
29920,97,0,110,0, 364573,0,102,0,83,
2993103,0,101,0,1,
2994117,1,2,2,0,
29951,1478,522,18,1,
29961478,160,2,0,1,
29971479,523,18,1,1479,
2998276,2,0,1,2037,
2999524,18,1,2037,191,
30002,0,1,2038,525,
300118,1,2038,526,20,
3002527,4,18,74,0,
3003117,0,109,0,112,
30040,76,0,97,0,
300598,0,101,0,108,
30060,1,115,1,2,
30072,0,1,2039,528,
300818,1,2039,191,2,
30090,1,2040,529,18,
30101,2040,530,20,531,
30114,30,82,0,101,
30120,116,0,117,0,
3013114,0,110,0,83,
30140,116,0,97,0, 36460,116,0,97,0,
3015116,0,101,0,109, 3647116,0,101,0,109,
30160,101,0,110,0, 36480,101,0,110,0,
3017116,0,1,114,1, 3649116,0,1,142,1,
30182,2,0,1,2041, 36502,2,0,1,2034,
3019532,18,1,2041,191, 3651597,18,1,2034,598,
30202,0,1,1485,533, 365220,599,4,22,83,
302118,1,1485,168,2, 36530,116,0,97,0,
30220,1,372,534,18, 3654116,0,101,0,67,
30231,372,180,2,0, 36550,104,0,97,0,
30241,373,535,18,1, 3656110,0,103,0,101,
3025373,132,2,0,1, 36570,1,141,1,2,
3026374,536,18,1,374, 36582,0,1,1478,600,
3027176,2,0,1,375, 365918,1,1478,179,2,
3028537,18,1,375,132, 36600,1,1479,601,18,
30292,0,1,376,538, 36611,1479,305,2,0,
303018,1,376,183,2, 36621,2037,602,18,1,
30310,1,377,539,18, 36632037,146,2,0,1,
30321,377,132,2,0, 36642038,603,18,1,2038,
30331,378,540,18,1, 3665604,20,605,4,18,
3034378,176,2,0,1, 366674,0,117,0,109,
3035379,541,18,1,379, 36670,112,0,76,0,
3036132,2,0,1,380, 366897,0,98,0,101,
3037542,18,1,380,543, 36690,108,0,1,139,
303820,544,4,16,67, 36701,2,2,0,1,
30390,111,0,110,0, 36712039,606,18,1,2039,
3040115,0,116,0,97, 3672146,2,0,1,2040,
3673607,18,1,2040,608,
367420,609,4,30,82,
36750,101,0,116,0,
3676117,0,114,0,110,
36770,83,0,116,0,
367897,0,116,0,101,
36790,109,0,101,0,
3680110,0,116,0,1,
3681138,1,2,2,0,
36821,2041,610,18,1,
36832041,146,2,0,1,
36841485,611,18,1,1485,
3685187,2,0,1,372,
3686612,18,1,372,199,
36872,0,1,373,613,
368818,1,373,132,2,
36890,1,374,614,18,
36901,374,195,2,0,
36911,375,615,18,1,
3692375,132,2,0,1,
3693376,616,18,1,376,
3694202,2,0,1,377,
3695617,18,1,377,132,
36962,0,1,378,618,
369718,1,378,195,2,
36980,1,379,619,18,
36991,379,132,2,0,
37001,380,620,18,1,
3701380,621,20,622,4,
370216,67,0,111,0,
3703110,0,115,0,116,
37040,97,0,110,0,
3705116,0,1,151,1,
37062,2,0,1,381,
3707623,18,1,381,323,
37082,0,1,371,624,
370918,1,371,625,20,
3710626,4,24,70,0,
3711117,0,110,0,99,
37120,116,0,105,0,
3713111,0,110,0,67,
37140,97,0,108,0,
3715108,0,1,147,1,
37162,2,0,1,942,
3717627,18,1,942,187,
37182,0,1,2533,628,
371918,1,2533,162,2,
37200,1,387,629,18,
37211,387,187,2,0,
37221,2536,630,18,1,
37232536,631,20,632,4,
372434,73,0,110,0,
3725116,0,82,0,111,
37260,116,0,82,0,
3727111,0,116,0,65,
37280,114,0,103,0,
372969,0,118,0,101,
30410,110,0,116,0, 37300,110,0,116,0,
30421,127,1,2,2, 37311,129,1,2,2,
30430,1,381,545,18, 37320,1,2537,633,18,
30441,381,290,2,0, 37331,2537,135,2,0,
30451,371,546,18,1, 37341,2543,634,18,1,
3046371,547,20,548,4, 37352543,635,20,636,4,
304724,70,0,117,0, 373628,82,0,111,0,
3048110,0,99,0,116, 3737116,0,68,0,101,
30490,105,0,111,0, 37380,99,0,108,0,
3050110,0,67,0,97, 373997,0,114,0,97,
30510,108,0,108,0, 37400,116,0,105,0,
30521,123,1,2,2, 3741111,0,110,0,1,
30530,1,942,549,18, 3742122,1,2,2,0,
30541,942,168,2,0, 37431,2546,637,18,1,
30551,387,550,18,1, 37442546,635,2,0,1,
3056387,168,2,0,1, 37451514,638,18,1,1514,
30571514,551,18,1,1514, 3746179,2,0,1,1515,
3058160,2,0,1,1515, 3747639,18,1,1515,333,
3059552,18,1,1515,256, 37482,0,1,2074,640,
30602,0,1,2074,553, 374918,1,2074,179,2,
306118,1,2074,160,2, 37500,1,2075,641,18,
30620,1,2075,554,18, 37511,2075,162,2,0,
30631,2075,153,2,0, 37521,2552,642,18,1,
30641,406,555,18,1, 37532552,135,2,0,1,
3065406,143,2,0,1, 3754406,643,18,1,406,
30661521,556,18,1,1521, 3755143,2,0,1,1521,
3067168,2,0,1,2636, 3756644,18,1,1521,187,
3068557,18,1,2636,295, 37572,0,1,2556,645,
30692,0,1,2557,558, 375818,1,2556,162,2,
307018,1,2557,462,2, 37590,1,2639,646,18,
30710,1,2639,559,18, 37601,2639,647,20,648,
30721,2639,560,20,561, 37614,44,75,0,101,
30734,10,83,0,116, 37620,121,0,73,0,
30740,97,0,116,0, 3763110,0,116,0,73,
3075101,0,1,101,1,
30762,2,0,1,412,
3077562,18,1,412,168,
30782,0,1,2641,563,
307918,1,2641,132,2,
30800,1,2484,564,18,
30811,2484,565,20,566,
30824,46,78,0,79,
30830,84,0,95,0,
308465,0,84,0,95,
30850,82,0,79,0,
308684,0,95,0,84,
30870,65,0,82,0,
308871,0,69,0,84,
30890,95,0,69,0,
309086,0,69,0,78,
30910,84,0,1,78,
30921,1,2,0,1,
30932023,567,18,1,2023,
3094465,2,0,1,1442,
3095568,18,1,1442,160,
30962,0,1,2651,569,
309718,1,2651,140,2,
30980,1,2653,570,18,
30991,2653,153,2,0,
31001,2655,571,18,1,
31012655,334,2,0,1,
31022035,572,18,1,2035,
3103191,2,0,1,2036,
3104573,18,1,2036,574,
310520,575,4,26,74,
31060,117,0,109,0,
3107112,0,83,0,116,
31080,97,0,116,0,
3109101,0,109,0,101,
31100,110,0,116,0, 37640,110,0,116,0,
31111,116,1,2,2, 376565,0,114,0,103,
31120,1,431,576,18, 37660,83,0,116,0,
31131,431,143,2,0, 376797,0,116,0,101,
31141,2105,577,18,1, 37680,69,0,118,0,
31152105,260,2,0,1, 3769101,0,110,0,116,
31162106,578,18,1,2106, 37700,1,110,1,2,
3117452,2,0,1,1550, 37712,0,1,412,649,
3118579,18,1,1550,160, 377218,1,412,187,2,
31192,0,1,437,580, 37730,1,2641,650,18,
312018,1,437,168,2, 37741,2641,168,2,0,
31210,1,2044,581,18, 37751,2484,651,18,1,
31221,2044,582,20,583, 37762484,652,20,653,4,
31234,28,69,0,109, 377738,67,0,79,0,
31240,112,0,116,0, 377876,0,76,0,73,
3125121,0,83,0,116, 37790,83,0,73,0,
378079,0,78,0,95,
37810,69,0,78,0,
378268,0,95,0,69,
37830,86,0,69,0,
378478,0,84,0,1,
378563,1,1,2,0,
37861,2643,654,18,1,
37872643,174,2,0,1,
37882644,655,18,1,2644,
3789656,20,657,4,32,
379075,0,101,0,121,
37910,65,0,114,0,
3792103,0,83,0,116,
31260,97,0,116,0, 37930,97,0,116,0,
3127101,0,109,0,101, 3794101,0,69,0,118,
37950,101,0,110,0,
3796116,0,1,105,1,
37972,2,0,1,2023,
3798658,18,1,2023,659,
379920,660,4,26,68,
38000,69,0,70,0,
380165,0,85,0,76,
38020,84,0,95,0,
380383,0,84,0,65,
38040,84,0,69,0,
38051,47,1,1,2,
38060,1,2564,661,18,
38071,2564,162,2,0,
38081,2647,662,18,1,
38092647,507,2,0,1,
38102648,663,18,1,2648,
3811647,2,0,1,2567,
3812664,18,1,2567,665,
381320,666,4,22,75,
38140,101,0,121,0,
381565,0,114,0,103,
38160,69,0,118,0,
3817101,0,110,0,116,
38180,1,126,1,2,
38192,0,1,1442,667,
382018,1,1442,179,2,
38210,1,2651,668,18,
38221,2651,669,20,670,
38234,38,86,0,101,
38240,99,0,116,0,
3825111,0,114,0,65,
38260,114,0,103,0,
382783,0,116,0,97,
38280,116,0,101,0,
382969,0,118,0,101,
31280,110,0,116,0, 38300,110,0,116,0,
31291,111,1,2,2, 38311,107,1,2,2,
31300,1,2045,584,18, 38320,1,2570,671,18,
31311,2045,191,2,0, 38331,2570,473,2,0,
31321,1555,585,18,1, 38341,2653,672,18,1,
31331555,168,2,0,1, 38352653,656,2,0,1,
31341001,586,18,1,1001, 38362572,673,18,1,2572,
3135547,2,0,1,1002, 3837162,2,0,1,2655,
3136587,18,1,1002,543, 3838674,18,1,2655,156,
31372,0,1,447,588, 38392,0,1,2574,675,
313818,1,447,307,2, 384018,1,2574,327,2,
31390,1,2597,589,18, 38410,1,2035,676,18,
31401,2597,590,20,591, 38421,2035,146,2,0,
31414,18,83,0,116, 38431,2036,677,18,1,
31420,97,0,116,0, 38442036,678,20,679,4,
3143101,0,66,0,111, 384526,74,0,117,0,
31440,100,0,121,0, 3846109,0,112,0,83,
31451,102,1,2,2, 38470,116,0,97,0,
31460,1,1010,592,18, 3848116,0,101,0,109,
31471,1010,160,2,0, 38490,101,0,110,0,
31481,1011,593,18,1, 3850116,0,1,140,1,
31491011,153,2,0,1, 38512,2,0,1,431,
31501012,594,18,1,1012, 3852680,18,1,431,143,
3151168,2,0,1,1013, 38532,0,1,2579,681,
3152595,18,1,1013,153, 385418,1,2579,327,2,
31532,0,1,459,596, 38550,1,2105,682,18,
315418,1,459,597,20, 38561,2105,285,2,0,
3155598,4,24,76,0, 38571,2106,683,18,1,
315669,0,70,0,84, 38582106,517,2,0,1,
31570,95,0,66,0, 38591550,684,18,1,1550,
315882,0,65,0,67, 3860179,2,0,1,437,
31590,75,0,69,0, 3861685,18,1,437,187,
316084,0,1,27,1, 38622,0,1,2044,686,
31611,2,0,1,1574, 386318,1,2044,687,20,
3162599,18,1,1574,191, 3864688,4,28,69,0,
31632,0,1,461,600, 3865109,0,112,0,116,
316418,1,461,601,20, 38660,121,0,83,0,
3165602,4,24,65,0, 3867116,0,97,0,116,
3166114,0,103,0,117, 38680,101,0,109,0,
31670,109,0,101,0, 3869101,0,110,0,116,
3168110,0,116,0,76, 38700,1,135,1,2,
31690,105,0,115,0, 38712,0,1,2045,689,
3170116,0,1,124,1, 387218,1,2045,146,2,
31712,2,0,1,462, 38730,1,1555,690,18,
3172603,18,1,462,143, 38741,1555,187,2,0,
31732,0,1,464,604, 38751,2511,691,18,1,
317418,1,464,605,20, 38762511,126,2,0,1,
3175606,4,16,65,0, 38771001,692,18,1,1001,
3176114,0,103,0,117, 3878625,2,0,1,1002,
31770,109,0,101,0, 3879693,18,1,1002,621,
3178110,0,116,0,1, 38802,0,1,447,694,
3179125,1,2,2,0, 388118,1,447,342,2,
31801,2136,607,18,1, 38820,1,2594,695,18,
31812136,260,2,0,1, 38831,2594,327,2,0,
31822694,608,18,1,2694, 38841,2596,696,18,1,
3183191,2,0,1,2695, 38852596,697,20,698,4,
3184609,18,1,2695,610, 388618,83,0,116,0,
318520,611,4,34,71, 388797,0,116,0,101,
31860,108,0,111,0, 38880,66,0,111,0,
318798,0,97,0,108, 3889100,0,121,0,1,
31880,68,0,101,0, 3890102,1,2,2,0,
3189102,0,105,0,110, 38911,2520,699,18,1,
31900,105,0,116,0, 38922520,327,2,0,1,
3191105,0,111,0,110, 38931010,700,18,1,1010,
31920,115,0,1,97, 3894179,2,0,1,1011,
31931,2,2,0,1, 3895701,18,1,1011,162,
31941585,612,18,1,1585, 38962,0,1,1012,702,
3195613,20,614,4,12, 389718,1,1012,187,2,
319682,0,69,0,84, 38980,1,1013,703,18,
31970,85,0,82,0, 38991,1013,162,2,0,
319878,0,1,50,1, 39001,459,704,18,1,
31991,2,0,1,476, 3901459,705,20,706,4,
3200615,18,1,476,616, 390224,76,0,69,0,
320120,617,4,30,83, 390370,0,84,0,95,
32020,84,0,82,0, 39040,66,0,82,0,
320373,0,78,0,71, 390565,0,67,0,75,
32040,95,0,67,0, 39060,69,0,84,0,
320579,0,78,0,83, 39071,27,1,1,2,
32060,84,0,65,0, 39080,1,1574,707,18,
320778,0,84,0,1, 39091,1574,146,2,0,
32083,1,1,2,0, 39101,461,708,18,1,
32091,477,618,18,1, 3911461,709,20,710,4,
3210477,619,20,620,4, 391224,65,0,114,0,
321128,70,0,76,0, 3913103,0,117,0,109,
321279,0,65,0,84, 39140,101,0,110,0,
32130,95,0,67,0, 3915116,0,76,0,105,
321479,0,78,0,83, 39160,115,0,116,0,
32150,84,0,65,0, 39171,148,1,2,2,
321678,0,84,0,1, 39180,1,462,711,18,
321795,1,1,2,0, 39191,462,143,2,0,
32181,478,621,18,1, 39201,464,712,18,1,
3219478,622,20,623,4, 3921464,713,20,714,4,
322040,72,0,69,0, 392216,65,0,114,0,
322188,0,95,0,73, 3923103,0,117,0,109,
32220,78,0,84,0, 39240,101,0,110,0,
322369,0,71,0,69, 3925116,0,1,149,1,
32240,82,0,95,0, 39262,2,0,1,2136,
3927715,18,1,2136,285,
39282,0,1,1585,716,
392918,1,1585,717,20,
3930718,4,12,82,0,
393169,0,84,0,85,
39320,82,0,78,0,
39331,50,1,1,2,
39340,1,2700,719,18,
39351,2700,697,2,0,
39361,476,720,18,1,
3937476,721,20,722,4,
393830,83,0,84,0,
393982,0,73,0,78,
39400,71,0,95,0,
322567,0,79,0,78, 394167,0,79,0,78,
32260,83,0,84,0, 39420,83,0,84,0,
322765,0,78,0,84, 394365,0,78,0,84,
32280,1,94,1,1, 39440,1,3,1,1,
32292,0,1,479,624, 39452,0,1,477,723,
323018,1,479,625,20, 394618,1,477,724,20,
3231626,4,32,73,0, 3947725,4,28,70,0,
323278,0,84,0,69, 394876,0,79,0,65,
32330,71,0,69,0, 39490,84,0,95,0,
323482,0,95,0,67, 395067,0,79,0,78,
32350,79,0,78,0, 39510,83,0,84,0,
323683,0,84,0,65, 395265,0,78,0,84,
32370,78,0,84,0, 39530,1,95,1,1,
32381,93,1,1,2, 39542,0,1,478,726,
32390,1,480,627,18, 395518,1,478,727,20,
32401,480,628,20,629, 3956728,4,40,72,0,
32414,26,82,0,73, 395769,0,88,0,95,
32420,71,0,72,0, 39580,73,0,78,0,
324384,0,95,0,66, 395984,0,69,0,71,
32440,82,0,65,0, 39600,69,0,82,0,
324567,0,75,0,69, 396195,0,67,0,79,
32460,84,0,1,28, 39620,78,0,83,0,
396384,0,65,0,78,
39640,84,0,1,94,
32471,1,2,0,1, 39651,1,2,0,1,
3248481,630,18,1,481, 3966479,729,18,1,479,
3249605,2,0,1,2713, 3967730,20,731,4,32,
3250631,18,1,2713,632, 396873,0,78,0,84,
325120,633,4,48,71, 39690,69,0,71,0,
32520,108,0,111,0, 397069,0,82,0,95,
325398,0,97,0,108, 39710,67,0,79,0,
32540,70,0,117,0, 397278,0,83,0,84,
3255110,0,99,0,116, 39730,65,0,78,0,
32560,105,0,111,0, 397484,0,1,93,1,
3257110,0,68,0,101, 39751,2,0,1,480,
32580,102,0,105,0, 3976732,18,1,480,733,
3259110,0,105,0,116, 397720,734,4,26,82,
39780,73,0,71,0,
397972,0,84,0,95,
39800,66,0,82,0,
398165,0,67,0,75,
39820,69,0,84,0,
39831,28,1,1,2,
39840,1,481,735,18,
39851,481,713,2,0,
39861,2550,736,18,1,
39872550,327,2,0,1,
39882554,737,18,1,2554,
3989308,2,0,1,1048,
3990738,18,1,1048,187,
39912,0,1,2640,739,
399218,1,2640,740,20,
3993741,4,44,73,0,
3994110,0,116,0,86,
39950,101,0,99,0,
399686,0,101,0,99,
39970,65,0,114,0,
3998103,0,83,0,116,
39990,97,0,116,0,
4000101,0,69,0,118,
40010,101,0,110,0,
4002116,0,1,109,1,
40032,2,0,1,2642,
4004742,18,1,2642,669,
40052,0,1,2563,743,
400618,1,2563,744,20,
4007745,4,52,73,0,
4008110,0,116,0,65,
40090,114,0,103,0,
4010117,0,109,0,101,
40110,110,0,116,0,
401268,0,101,0,99,
40130,108,0,97,0,
4014114,0,97,0,116,
32600,105,0,111,0, 40150,105,0,111,0,
3261110,0,1,99,1, 4016110,0,76,0,105,
32622,2,0,1,2714, 40170,115,0,116,0,
3263634,18,1,2714,635, 40181,113,1,2,2,
326420,636,4,50,71, 40190,1,2042,746,18,
32650,108,0,111,0, 40201,2042,747,20,748,
326698,0,97,0,108, 40214,20,65,0,115,
32670,86,0,97,0, 40220,115,0,105,0,
3268114,0,105,0,97, 4023103,0,110,0,109,
32690,98,0,108,0,
3270101,0,68,0,101,
32710,99,0,108,0,
327297,0,114,0,97,
32730,116,0,105,0,
3274111,0,110,0,1,
327598,1,2,2,0,
32761,2715,637,18,1,
32772715,632,2,0,1,
32782716,638,18,1,2716,
3279635,2,0,1,2717,
3280104,1,2634,639,18,
32811,2634,447,2,0,
32821,1048,640,18,1,
32831048,168,2,0,1,
32842640,641,18,1,2640,
3285560,2,0,1,2642,
3286642,18,1,2642,135,
32872,0,1,2042,643,
328818,1,2042,644,20,
3289645,4,20,65,0,
3290115,0,115,0,105,
32910,103,0,110,0,
3292109,0,101,0,110,
32930,116,0,1,112,
32941,2,2,0,1,
32952043,646,18,1,2043,
3296191,2,0,1,1620,
3297647,18,1,1620,160,
32982,0,1,1621,648,
329918,1,1621,150,2,
33000,1,1622,649,18,
33011,1622,256,2,0,
33021,509,650,18,1,
3303509,143,2,0,1,
33042498,651,18,1,2498,
3305652,20,653,4,42,
330667,0,79,0,76,
33070,76,0,73,0,
330883,0,73,0,79,
33090,78,0,95,0,
331083,0,84,0,65,
33110,82,0,84,0,
331295,0,69,0,86,
33130,69,0,78,0,
331484,0,1,64,1,
33151,2,0,1,1628,
3316654,18,1,1628,168,
33172,0,1,515,655,
331818,1,515,168,2,
33190,1,2505,656,18,
33201,2505,657,20,658,
33214,10,69,0,118,
33220,101,0,110,0, 40240,101,0,110,0,
3323116,0,1,107,1, 4025116,0,1,136,1,
33242,2,0,1,2664, 40262,2,0,1,2043,
3325659,18,1,2664,168, 4027749,18,1,2043,146,
33262,0,1,525,660, 40282,0,1,2568,750,
332718,1,525,307,2, 402918,1,2568,135,2,
33280,1,2197,661,18, 40300,1,2649,751,18,
33291,2197,160,2,0, 40311,2649,740,2,0,
33301,2198,662,18,1, 40321,1620,752,18,1,
33312198,153,2,0,1, 40331620,179,2,0,1,
33321591,663,18,1,1591, 40341621,753,18,1,1621,
3333168,2,0,1,2521, 4035159,2,0,1,1622,
3334664,18,1,2521,590, 4036754,18,1,1622,333,
33352,0,1,1094,665, 40372,0,1,509,755,
333618,1,1094,601,2, 403818,1,509,143,2,
33370,1,1096,666,18, 40390,1,2498,756,18,
33381,1096,153,2,0, 40401,2498,757,20,758,
33391,2683,667,18,1, 40414,34,82,0,69,
33402683,191,2,0,1, 40420,77,0,79,0,
33411657,668,18,1,1657, 404384,0,69,0,95,
3342191,2,0,1,1658, 40440,68,0,65,0,
3343669,18,1,1658,670, 404584,0,65,0,95,
334420,671,4,6,70, 40460,69,0,86,0,
33450,79,0,82,0, 404769,0,78,0,84,
33461,46,1,1,2, 40480,1,82,1,1,
33470,1,1659,672,18, 40492,0,1,2576,759,
33481,1659,135,2,0, 405018,1,2576,135,2,
33491,1665,673,18,1, 40510,1,2656,760,18,
33501665,168,2,0,1, 40521,2656,659,2,0,
33511113,674,18,1,1113, 40531,1628,761,18,1,
3352176,2,0,675,5, 40541628,187,2,0,1,
33530,676,5,324,1, 4055515,762,18,1,515,
33542,677,19,237,1, 4056187,2,0,1,2580,
33552,678,5,6,1, 4057763,18,1,2580,764,
33562706,679,17,680,15, 405820,765,4,10,69,
3357681,4,30,37,0, 40590,118,0,101,0,
4060110,0,116,0,1,
4061124,1,2,2,0,
40621,2505,766,18,1,
40632505,767,20,768,4,
406434,75,0,101,0,
4065121,0,73,0,110,
40660,116,0,73,0,
4067110,0,116,0,65,
40680,114,0,103,0,
406969,0,118,0,101,
40700,110,0,116,0,
40711,131,1,2,2,
40720,1,2751,769,18,
40731,2751,507,2,0,
40741,525,770,18,1,
4075525,342,2,0,1,
40762197,771,18,1,2197,
4077179,2,0,1,2198,
4078772,18,1,2198,162,
40792,0,1,1591,773,
408018,1,1591,187,2,
40810,1,2592,774,18,
40821,2592,162,2,0,
40831,2760,775,18,1,
40842760,291,2,0,1,
40852521,776,18,1,2521,
4086777,20,778,4,34,
408773,0,110,0,116,
40880,86,0,101,0,
408999,0,86,0,101,
40900,99,0,65,0,
4091114,0,103,0,69,
40920,118,0,101,0,
4093110,0,116,0,1,
4094130,1,2,2,0,
40951,2763,779,18,1,
40962763,780,20,781,4,
409710,83,0,116,0,
409897,0,116,0,101,
40990,1,101,1,2,
41002,0,1,2764,782,
410118,1,2764,780,2,
41020,1,1094,783,18,
41031,1094,709,2,0,
41041,2766,784,18,1,
41052766,135,2,0,1,
41061096,785,18,1,1096,
4107162,2,0,1,1657,
4108786,18,1,1657,146,
41092,0,1,1658,787,
411018,1,1658,788,20,
4111789,4,6,70,0,
411279,0,82,0,1,
411346,1,1,2,0,
41141,1659,790,18,1,
41151659,135,2,0,1,
41162775,791,18,1,2775,
4117140,2,0,1,2777,
4118792,18,1,2777,162,
41192,0,1,1665,793,
412018,1,1665,187,2,
41210,1,2781,794,18,
41221,2781,159,2,0,
41231,2782,795,18,1,
41242782,333,2,0,1,
41251113,796,18,1,1113,
4126195,2,0,797,5,
41270,798,5,379,1,
41282,799,19,216,1,
41292,800,5,6,1,
41302764,801,17,802,15,
4131803,4,14,37,0,
413283,0,116,0,97,
41330,116,0,101,0,
4134115,0,1,-1,1,
41355,804,20,805,4,
413616,83,0,116,0,
413797,0,116,0,101,
41380,115,0,95,0,
413949,0,1,176,1,
41403,1,2,1,1,
4141806,22,1,11,1,
41422751,807,17,808,15,
4143809,4,12,37,0,
414483,0,116,0,97,
41450,116,0,101,0,
41461,-1,1,5,810,
414720,811,4,14,83,
41480,116,0,97,0,
4149116,0,101,0,95,
41500,49,0,1,178,
41511,3,1,5,1,
41524,812,22,1,13,
41531,2763,813,17,814,
415415,803,1,-1,1,
41555,815,20,816,4,
415616,83,0,116,0,
415797,0,116,0,101,
41580,115,0,95,0,
415950,0,1,177,1,
41603,1,3,1,2,
4161817,22,1,12,1,
41622830,818,17,819,15,
4163820,4,30,37,0,
335876,0,83,0,76, 416476,0,83,0,76,
33590,80,0,114,0, 41650,80,0,114,0,
3360111,0,103,0,114, 4166111,0,103,0,114,
33610,97,0,109,0, 41670,97,0,109,0,
336282,0,111,0,111, 416882,0,111,0,111,
33630,116,0,1,-1, 41690,116,0,1,-1,
33641,5,682,20,683, 41701,5,821,20,822,
33654,32,76,0,83, 41714,32,76,0,83,
33660,76,0,80,0, 41720,76,0,80,0,
3367114,0,111,0,103, 4173114,0,111,0,103,
@@ -3369,265 +4175,233 @@ public yyLSLSyntax
3369109,0,82,0,111, 4175109,0,82,0,111,
33700,111,0,116,0, 41760,111,0,116,0,
337195,0,49,0,1, 417795,0,49,0,1,
3372142,1,3,1,3, 4178166,1,3,1,3,
33731,2,684,22,1, 41791,2,823,22,1,
33741,1,2640,685,17, 41801,1,2647,824,17,
3375686,15,687,4,14, 4181825,15,809,1,-1,
337637,0,83,0,116, 41821,5,826,20,827,
33770,97,0,116,0, 41834,14,83,0,116,
3378101,0,115,0,1,
3379-1,1,5,688,20,
3380689,4,16,83,0,
3381116,0,97,0,116,
33820,101,0,115,0,
338395,0,49,0,1,
3384152,1,3,1,2,
33851,1,690,22,1,
338611,1,2634,691,17,
3387692,15,693,4,12,
338837,0,83,0,116,
33890,97,0,116,0, 41840,97,0,116,0,
3390101,0,1,-1,1, 4185101,0,95,0,50,
33915,694,20,695,4, 41860,1,179,1,3,
339214,83,0,116,0, 41871,6,1,5,828,
339397,0,116,0,101, 418822,1,14,1,2760,
33940,95,0,49,0, 4189829,17,830,15,820,
33951,154,1,3,1, 41901,-1,1,5,831,
33965,1,4,696,22, 419120,832,4,32,76,
33971,13,1,2558,697, 41920,83,0,76,0,
339817,698,15,693,1, 419380,0,114,0,111,
3399-1,1,5,699,20, 41940,103,0,114,0,
3400700,4,14,83,0, 419597,0,109,0,82,
3401116,0,97,0,116, 41960,111,0,111,0,
34020,101,0,95,0, 4197116,0,95,0,50,
340350,0,1,155,1, 41980,1,167,1,3,
34043,1,6,1,5, 41991,2,1,1,833,
3405701,22,1,14,1, 420022,1,2,1,3,
34062636,702,17,703,15, 4201834,19,722,1,3,
3407681,1,-1,1,5, 4202835,5,95,1,256,
3408704,20,705,4,32, 4203836,16,0,720,1,
340976,0,83,0,76, 42041261,837,16,0,720,
34100,80,0,114,0, 42051,509,838,16,0,
3411111,0,103,0,114, 4206720,1,1515,839,16,
34120,97,0,109,0, 42070,720,1,2021,840,
341382,0,111,0,111, 420817,841,15,842,4,
34140,116,0,95,0,
341550,0,1,143,1,
34163,1,2,1,1,
3417706,22,1,2,1,
34182639,707,17,708,15,
3419687,1,-1,1,5,
3420709,20,710,4,16,
342183,0,116,0,97,
34220,116,0,101,0,
3423115,0,95,0,50,
34240,1,153,1,3,
34251,3,1,2,711,
342622,1,12,1,3,
3427712,19,617,1,3,
3428713,5,95,1,256,
3429714,16,0,615,1,
34301261,715,16,0,615,
34311,509,716,16,0,
3432615,1,1515,717,16,
34330,615,1,2021,718,
343417,719,15,720,4,
343524,37,0,73,0, 420924,37,0,73,0,
3436102,0,83,0,116, 4210102,0,83,0,116,
34370,97,0,116,0, 42110,97,0,116,0,
3438101,0,109,0,101, 4212101,0,109,0,101,
34390,110,0,116,0, 42130,110,0,116,0,
34401,-1,1,5,721, 42141,-1,1,5,843,
344120,722,4,26,73, 421520,844,4,26,73,
34420,102,0,83,0, 42160,102,0,83,0,
3443116,0,97,0,116, 4217116,0,97,0,116,
34440,101,0,109,0, 42180,101,0,109,0,
3445101,0,110,0,116, 4219101,0,110,0,116,
34460,95,0,50,0, 42200,95,0,50,0,
34471,185,1,3,1, 42211,240,1,3,1,
34488,1,7,723,22, 42228,1,7,845,22,
34491,45,1,1775,724, 42231,76,1,1775,846,
345016,0,615,1,2029, 422416,0,720,1,2029,
3451725,17,726,15,727, 4225847,17,848,15,849,
34524,20,37,0,83, 42264,20,37,0,83,
34530,116,0,97,0, 42270,116,0,97,0,
3454116,0,101,0,109, 4228116,0,101,0,109,
34550,101,0,110,0, 42290,101,0,110,0,
3456116,0,1,-1,1, 4230116,0,1,-1,1,
34575,728,20,729,4, 42315,850,20,851,4,
345824,83,0,116,0, 423224,83,0,116,0,
345997,0,116,0,101, 423397,0,116,0,101,
34600,109,0,101,0, 42340,109,0,101,0,
3461110,0,116,0,95, 4235110,0,116,0,95,
34620,49,0,51,0, 42360,49,0,51,0,
34631,179,1,3,1, 42371,234,1,3,1,
34642,1,1,730,22, 42382,1,1,852,22,
34651,39,1,2030,731, 42391,70,1,2030,853,
346617,732,15,727,1, 424017,854,15,849,1,
3467-1,1,5,733,20, 4241-1,1,5,855,20,
3468734,4,24,83,0, 4242856,4,24,83,0,
3469116,0,97,0,116, 4243116,0,97,0,116,
34700,101,0,109,0, 42440,101,0,109,0,
3471101,0,110,0,116, 4245101,0,110,0,116,
34720,95,0,49,0, 42460,95,0,49,0,
347350,0,1,178,1, 424750,0,1,233,1,
34743,1,2,1,1, 42483,1,2,1,1,
3475735,22,1,38,1, 4249857,22,1,69,1,
34762031,736,17,737,15, 42502031,858,17,859,15,
3477727,1,-1,1,5, 4251849,1,-1,1,5,
3478738,20,739,4,24, 4252860,20,861,4,24,
347983,0,116,0,97, 425383,0,116,0,97,
34800,116,0,101,0, 42540,116,0,101,0,
3481109,0,101,0,110, 4255109,0,101,0,110,
34820,116,0,95,0, 42560,116,0,95,0,
348349,0,49,0,1, 425749,0,49,0,1,
3484177,1,3,1,2, 4258232,1,3,1,2,
34851,1,740,22,1, 42591,1,862,22,1,
348637,1,2032,741,17, 426068,1,2032,863,17,
3487742,15,727,1,-1, 4261864,15,849,1,-1,
34881,5,743,20,744, 42621,5,865,20,866,
34894,24,83,0,116, 42634,24,83,0,116,
34900,97,0,116,0, 42640,97,0,116,0,
3491101,0,109,0,101, 4265101,0,109,0,101,
34920,110,0,116,0, 42660,110,0,116,0,
349395,0,49,0,48, 426795,0,49,0,48,
34940,1,176,1,3, 42680,1,231,1,3,
34951,2,1,1,745, 42691,2,1,1,867,
349622,1,36,1,2033, 427022,1,67,1,2033,
3497746,17,747,15,727, 4271868,17,869,15,849,
34981,-1,1,5,748, 42721,-1,1,5,870,
349920,749,4,22,83, 427320,871,4,22,83,
35000,116,0,97,0, 42740,116,0,97,0,
3501116,0,101,0,109, 4275116,0,101,0,109,
35020,101,0,110,0, 42760,101,0,110,0,
3503116,0,95,0,57, 4277116,0,95,0,57,
35040,1,175,1,3, 42780,1,230,1,3,
35051,2,1,1,750, 42791,2,1,1,872,
350622,1,35,1,277, 428022,1,66,1,277,
3507751,16,0,615,1, 4281873,16,0,720,1,
35082035,752,17,753,15, 42822035,874,17,875,15,
3509727,1,-1,1,5, 4283849,1,-1,1,5,
3510754,20,755,4,22, 4284876,20,877,4,22,
351183,0,116,0,97, 428583,0,116,0,97,
35120,116,0,101,0, 42860,116,0,101,0,
3513109,0,101,0,110, 4287109,0,101,0,110,
35140,116,0,95,0, 42880,116,0,95,0,
351556,0,1,174,1, 428956,0,1,229,1,
35163,1,3,1,2, 42903,1,3,1,2,
3517756,22,1,34,1, 4291878,22,1,65,1,
35182037,757,17,758,15, 42922037,879,17,880,15,
3519727,1,-1,1,5, 4293849,1,-1,1,5,
3520759,20,760,4,22, 4294881,20,882,4,22,
352183,0,116,0,97, 429583,0,116,0,97,
35220,116,0,101,0, 42960,116,0,101,0,
3523109,0,101,0,110, 4297109,0,101,0,110,
35240,116,0,95,0, 42980,116,0,95,0,
352555,0,1,173,1, 429955,0,1,228,1,
35263,1,3,1,2, 43003,1,3,1,2,
3527761,22,1,33,1, 4301883,22,1,64,1,
35282039,762,17,763,15, 43022039,884,17,885,15,
3529727,1,-1,1,5, 4303849,1,-1,1,5,
3530764,20,765,4,22, 4304886,20,887,4,22,
353183,0,116,0,97, 430583,0,116,0,97,
35320,116,0,101,0, 43060,116,0,101,0,
3533109,0,101,0,110, 4307109,0,101,0,110,
35340,116,0,95,0, 43080,116,0,95,0,
353554,0,1,172,1, 430954,0,1,227,1,
35363,1,3,1,2, 43103,1,3,1,2,
3537766,22,1,32,1, 4311888,22,1,63,1,
353832,767,16,0,615, 431232,889,16,0,720,
35391,2041,768,17,769, 43131,2041,890,17,891,
354015,727,1,-1,1, 431415,849,1,-1,1,
35415,770,20,771,4, 43155,892,20,893,4,
354222,83,0,116,0, 431622,83,0,116,0,
354397,0,116,0,101, 431797,0,116,0,101,
35440,109,0,101,0, 43180,109,0,101,0,
3545110,0,116,0,95, 4319110,0,116,0,95,
35460,53,0,1,171, 43200,53,0,1,226,
35471,3,1,3,1, 43211,3,1,3,1,
35482,772,22,1,31, 43222,894,22,1,62,
35491,2293,773,16,0, 43231,2293,895,16,0,
3550615,1,2043,774,17, 4324720,1,2043,896,17,
3551775,15,727,1,-1, 4325897,15,849,1,-1,
35521,5,776,20,777, 43261,5,898,20,899,
35534,22,83,0,116, 43274,22,83,0,116,
35540,97,0,116,0, 43280,97,0,116,0,
3555101,0,109,0,101, 4329101,0,109,0,101,
35560,110,0,116,0, 43300,110,0,116,0,
355795,0,51,0,1, 433195,0,51,0,1,
3558169,1,3,1,3, 4332224,1,3,1,3,
35591,2,778,22,1, 43331,2,900,22,1,
356029,1,2045,779,17, 433460,1,2045,901,17,
3561780,15,727,1,-1, 4335902,15,849,1,-1,
35621,5,781,20,782, 43361,5,903,20,904,
35634,22,83,0,116, 43374,22,83,0,116,
35640,97,0,116,0, 43380,97,0,116,0,
3565101,0,109,0,101, 4339101,0,109,0,101,
35660,110,0,116,0, 43400,110,0,116,0,
356795,0,49,0,1, 434195,0,49,0,1,
3568167,1,3,1,3, 4342222,1,3,1,3,
35691,2,783,22,1, 43431,2,905,22,1,
357027,1,41,784,16, 434458,1,41,906,16,
35710,615,1,1297,785, 43450,720,1,1297,907,
357216,0,615,1,43, 434616,0,720,1,43,
3573786,16,0,615,1, 4347908,16,0,720,1,
35741803,787,17,788,15, 43481803,909,17,910,15,
3575789,4,16,37,0, 4349911,4,16,37,0,
357670,0,111,0,114, 435070,0,111,0,114,
35770,76,0,111,0, 43510,76,0,111,0,
3578111,0,112,0,1, 4352111,0,112,0,1,
3579-1,1,5,790,20, 4353-1,1,5,912,20,
3580791,4,18,70,0, 4354913,4,18,70,0,
3581111,0,114,0,76, 4355111,0,114,0,76,
35820,111,0,111,0, 43560,111,0,111,0,
3583112,0,95,0,49, 4357112,0,95,0,49,
35840,1,192,1,3, 43580,1,247,1,3,
35851,10,1,9,792, 43591,10,1,9,914,
358622,1,52,1,1804, 436022,1,83,1,1804,
3587793,16,0,615,1, 4361915,16,0,720,1,
3588299,794,16,0,615, 4362299,916,16,0,720,
35891,52,795,16,0, 43631,52,917,16,0,
3590615,1,2318,796,16, 4364720,1,2318,918,16,
35910,615,1,62,797, 43650,720,1,62,919,
359216,0,615,1,2075, 436616,0,720,1,2075,
3593798,16,0,615,1, 4367920,16,0,720,1,
35941574,799,17,800,15, 43681574,921,17,922,15,
3595727,1,-1,1,5, 4369849,1,-1,1,5,
3596801,20,802,4,22, 4370923,20,924,4,22,
359783,0,116,0,97, 437183,0,116,0,97,
35980,116,0,101,0, 43720,116,0,101,0,
3599109,0,101,0,110, 4373109,0,101,0,110,
36000,116,0,95,0, 43740,116,0,95,0,
360152,0,1,170,1, 437552,0,1,225,1,
36023,1,3,1,2, 43763,1,3,1,2,
3603803,22,1,30,1, 4377925,22,1,61,1,
360471,804,16,0,615, 437871,926,16,0,720,
36051,76,805,16,0, 43791,76,927,16,0,
3606615,1,1834,806,16, 4380720,1,1834,928,16,
36070,615,1,2337,807, 43810,720,1,2337,929,
360816,0,615,1,79, 438216,0,720,1,79,
3609808,16,0,615,1, 4383930,16,0,720,1,
36101335,809,16,0,615, 43841335,931,16,0,720,
36111,322,810,16,0, 43851,322,932,16,0,
3612615,1,85,811,16, 4386720,1,85,933,16,
36130,615,1,89,812, 43870,720,1,89,934,
361416,0,615,1,346, 438816,0,720,1,346,
3615813,16,0,615,1, 4389935,16,0,720,1,
36162105,814,17,815,15, 43902105,936,17,937,15,
3617720,1,-1,1,5, 4391842,1,-1,1,5,
3618816,20,817,4,26, 4392938,20,939,4,26,
361973,0,102,0,83, 439373,0,102,0,83,
36200,116,0,97,0, 43940,116,0,97,0,
3621116,0,101,0,109, 4395116,0,101,0,109,
36220,101,0,110,0, 43960,101,0,110,0,
3623116,0,95,0,51, 4397116,0,95,0,51,
36240,1,186,1,3, 43980,1,241,1,3,
36251,6,1,5,818, 43991,6,1,5,940,
362622,1,46,1,2106, 440022,1,77,1,2106,
3627819,16,0,615,1, 4401941,16,0,720,1,
362897,820,16,0,615, 440297,942,16,0,720,
36291,1860,821,17,822, 44031,1860,943,17,944,
363015,823,4,34,37, 440415,945,4,34,37,
36310,68,0,111,0, 44050,68,0,111,0,
363287,0,104,0,105, 440687,0,104,0,105,
36330,108,0,101,0, 44070,108,0,101,0,
@@ -3635,7 +4409,7 @@ public yyLSLSyntax
36350,116,0,101,0, 44090,116,0,101,0,
3636109,0,101,0,110, 4410109,0,101,0,110,
36370,116,0,1,-1, 44110,116,0,1,-1,
36381,5,824,20,825, 44121,5,946,20,947,
36394,36,68,0,111, 44134,36,68,0,111,
36400,87,0,104,0, 44140,87,0,104,0,
3641105,0,108,0,101, 4415105,0,108,0,101,
@@ -3643,66 +4417,66 @@ public yyLSLSyntax
364397,0,116,0,101, 441797,0,116,0,101,
36440,109,0,101,0, 44180,109,0,101,0,
3645110,0,116,0,95, 4419110,0,116,0,95,
36460,49,0,1,190, 44200,49,0,1,245,
36471,3,1,8,1, 44211,3,1,8,1,
36487,826,22,1,50, 44227,948,22,1,81,
36491,2364,827,17,828, 44231,2364,949,17,950,
365015,789,1,-1,1, 442415,911,1,-1,1,
36515,829,20,830,4, 44255,951,20,952,4,
365218,70,0,111,0, 442618,70,0,111,0,
3653114,0,76,0,111, 4427114,0,76,0,111,
36540,111,0,112,0, 44280,111,0,112,0,
365595,0,50,0,1, 442995,0,50,0,1,
3656193,1,3,1,9, 4430248,1,3,1,9,
36571,8,831,22,1, 44311,8,953,22,1,
365853,1,102,832,16, 443284,1,102,954,16,
36590,615,1,112,833, 44330,720,1,2782,955,
366016,0,615,1,1117, 443416,0,720,1,112,
3661834,16,0,615,1, 4435956,16,0,720,1,
36621873,835,17,836,15, 44361117,957,16,0,720,
3663823,1,-1,1,5, 44371,1873,958,17,959,
3664837,20,838,4,36, 443815,945,1,-1,1,
366568,0,111,0,87, 44395,960,20,961,4,
36660,104,0,105,0, 444036,68,0,111,0,
3667108,0,101,0,83, 444187,0,104,0,105,
36680,116,0,97,0, 44420,108,0,101,0,
3669116,0,101,0,109,
36700,101,0,110,0,
3671116,0,95,0,50,
36720,1,191,1,3,
36731,8,1,7,839,
367422,1,51,1,1876,
3675840,16,0,615,1,
3676124,841,16,0,615,
36771,2136,842,17,843,
367815,720,1,-1,1,
36795,844,20,845,4,
368026,73,0,102,0,
368183,0,116,0,97, 444383,0,116,0,97,
36820,116,0,101,0, 44440,116,0,101,0,
3683109,0,101,0,110, 4445109,0,101,0,110,
36840,116,0,95,0, 44460,116,0,95,0,
368552,0,1,187,1, 444750,0,1,246,1,
36863,1,8,1,7, 44483,1,8,1,7,
3687846,22,1,47,1, 4449962,22,1,82,1,
3688381,847,16,0,615, 44501876,963,16,0,720,
36891,525,848,16,0, 44511,124,964,16,0,
3690615,1,137,849,16, 4452720,1,2136,965,17,
36910,615,1,1901,850, 4453966,15,842,1,-1,
369216,0,615,1,2658, 44541,5,967,20,968,
3693851,16,0,615,1, 44554,26,73,0,102,
36941153,852,16,0,615, 44560,83,0,116,0,
36951,151,853,16,0, 445797,0,116,0,101,
3696615,1,1407,854,16, 44580,109,0,101,0,
36970,615,1,1659,855, 4459110,0,116,0,95,
369816,0,615,1,2413, 44600,52,0,1,242,
3699856,16,0,615,1, 44611,3,1,8,1,
3700406,857,16,0,615, 44627,969,22,1,78,
37011,1371,858,16,0, 44631,381,970,16,0,
3702615,1,166,859,16, 4464720,1,525,971,16,
37030,615,1,1622,860, 44650,720,1,137,972,
370416,0,615,1,1931, 446616,0,720,1,1901,
3705861,17,862,15,863, 4467973,16,0,720,1,
44681153,974,16,0,720,
44691,151,975,16,0,
4470720,1,1407,976,16,
44710,720,1,1659,977,
447216,0,720,1,2413,
4473978,16,0,720,1,
4474406,979,16,0,720,
44751,1371,980,16,0,
4476720,1,166,981,16,
44770,720,1,1622,982,
447816,0,720,1,1931,
4479983,17,984,15,985,
37064,30,37,0,87, 44804,30,37,0,87,
37070,104,0,105,0, 44810,104,0,105,0,
3708108,0,101,0,83, 4482108,0,101,0,83,
@@ -3710,46 +4484,46 @@ public yyLSLSyntax
3710116,0,101,0,109, 4484116,0,101,0,109,
37110,101,0,110,0, 44850,101,0,110,0,
3712116,0,1,-1,1, 4486116,0,1,-1,1,
37135,864,20,865,4, 44875,986,20,987,4,
371432,87,0,104,0, 448832,87,0,104,0,
3715105,0,108,0,101, 4489105,0,108,0,101,
37160,83,0,116,0, 44900,83,0,116,0,
371797,0,116,0,101, 449197,0,116,0,101,
37180,109,0,101,0, 44920,109,0,101,0,
3719110,0,116,0,95, 4493110,0,116,0,95,
37200,49,0,1,188, 44940,49,0,1,243,
37211,3,1,6,1, 44951,3,1,6,1,
37225,866,22,1,48, 44965,988,22,1,79,
37231,1933,867,16,0, 44971,1933,989,16,0,
3724615,1,431,868,16, 4498720,1,431,990,16,
37250,615,1,1585,869, 44990,720,1,1585,991,
372616,0,615,1,182, 450016,0,720,1,182,
3727870,16,0,615,1, 4501992,16,0,720,1,
37281189,871,16,0,615, 45021189,993,16,0,720,
37291,1443,872,16,0, 45031,1443,994,16,0,
3730615,1,1695,873,16, 4504720,1,1695,995,16,
37310,615,1,2198,874, 45050,720,1,2198,996,
373216,0,615,1,447, 450616,0,720,1,447,
3733875,16,0,615,1, 4507997,16,0,720,1,
37342458,876,17,877,15, 45082458,998,17,999,15,
3735878,4,28,37,0, 45091000,4,28,37,0,
373683,0,116,0,97, 451083,0,116,0,97,
37370,116,0,101,0, 45110,116,0,101,0,
3738109,0,101,0,110, 4512109,0,101,0,110,
37390,116,0,76,0, 45130,116,0,76,0,
3740105,0,115,0,116, 4514105,0,115,0,116,
37410,1,-1,1,5, 45150,1,-1,1,5,
3742879,20,880,4,30, 45161001,20,1002,4,30,
374383,0,116,0,97, 451783,0,116,0,97,
37440,116,0,101,0, 45180,116,0,101,0,
3745109,0,101,0,110, 4519109,0,101,0,110,
37460,116,0,76,0, 45200,116,0,76,0,
3747105,0,115,0,116, 4521105,0,115,0,116,
37480,95,0,50,0, 45220,95,0,50,0,
37491,165,1,3,1, 45231,220,1,3,1,
37503,1,2,881,22, 45243,1,2,1003,22,
37511,25,1,2459,882, 45251,56,1,2459,1004,
375217,883,15,884,4, 452617,1005,15,1006,4,
375336,37,0,67,0, 452736,37,0,67,0,
3754111,0,109,0,112, 4528111,0,109,0,112,
37550,111,0,117,0, 45290,111,0,117,0,
@@ -3758,7 +4532,7 @@ public yyLSLSyntax
3758116,0,101,0,109, 4532116,0,101,0,109,
37590,101,0,110,0, 45330,101,0,110,0,
3760116,0,1,-1,1, 4534116,0,1,-1,1,
37615,885,20,886,4, 45355,1007,20,1008,4,
376238,67,0,111,0, 453638,67,0,111,0,
3763109,0,112,0,111, 4537109,0,112,0,111,
37640,117,0,110,0, 45380,117,0,110,0,
@@ -3767,34 +4541,34 @@ public yyLSLSyntax
3767101,0,109,0,101, 4541101,0,109,0,101,
37680,110,0,116,0, 45420,110,0,116,0,
376995,0,50,0,1, 454395,0,50,0,1,
3770163,1,3,1,4, 4544218,1,3,1,4,
37711,3,887,22,1, 45451,3,1009,22,1,
377223,1,1958,888,16, 454654,1,1958,1010,16,
37730,615,1,2462,889, 45470,720,1,2462,1011,
377417,890,15,878,1, 454817,1012,15,1000,1,
3775-1,1,5,891,20, 4549-1,1,5,1013,20,
3776892,4,30,83,0, 45501014,4,30,83,0,
3777116,0,97,0,116, 4551116,0,97,0,116,
37780,101,0,109,0, 45520,101,0,109,0,
3779101,0,110,0,116, 4553101,0,110,0,116,
37800,76,0,105,0, 45540,76,0,105,0,
3781115,0,116,0,95, 4555115,0,116,0,95,
37820,49,0,1,164, 45560,49,0,1,219,
37831,3,1,2,1, 45571,3,1,2,1,
37841,893,22,1,24, 45581,1015,22,1,55,
37851,1657,894,17,895, 45591,1657,1016,17,1017,
378615,727,1,-1,1, 456015,849,1,-1,1,
37875,896,20,897,4, 45615,1018,20,1019,4,
378822,83,0,116,0, 456222,83,0,116,0,
378997,0,116,0,101, 456397,0,116,0,101,
37900,109,0,101,0, 45640,109,0,101,0,
3791110,0,116,0,95, 4565110,0,116,0,95,
37920,50,0,1,168, 45660,50,0,1,223,
37931,3,1,3,1, 45671,3,1,3,1,
37942,898,22,1,28, 45682,1020,22,1,59,
37951,2464,899,17,900, 45691,2464,1021,17,1022,
379615,884,1,-1,1, 457015,1006,1,-1,1,
37975,901,20,902,4, 45715,1023,20,1024,4,
379838,67,0,111,0, 457238,67,0,111,0,
3799109,0,112,0,111, 4573109,0,112,0,111,
38000,117,0,110,0, 45740,117,0,110,0,
@@ -3803,280 +4577,280 @@ public yyLSLSyntax
3803101,0,109,0,101, 4577101,0,109,0,101,
38040,110,0,116,0, 45780,110,0,116,0,
380595,0,49,0,1, 457995,0,49,0,1,
3806162,1,3,1,3, 4580217,1,3,1,3,
38071,2,903,22,1, 45811,2,1025,22,1,
380822,1,199,904,16, 458253,1,199,1026,16,
38090,615,1,459,905, 45830,720,1,459,1027,
381016,0,615,1,462, 458416,0,720,1,462,
3811906,16,0,615,1, 45851028,16,0,720,1,
3812217,907,16,0,615, 4586217,1029,16,0,720,
38131,2227,908,17,909, 45871,2227,1030,17,1031,
381415,863,1,-1,1, 458815,985,1,-1,1,
38155,910,20,911,4, 45895,1032,20,1033,4,
381632,87,0,104,0, 459032,87,0,104,0,
3817105,0,108,0,101, 4591105,0,108,0,101,
38180,83,0,116,0, 45920,83,0,116,0,
381997,0,116,0,101, 459397,0,116,0,101,
38200,109,0,101,0, 45940,109,0,101,0,
3821110,0,116,0,95, 4595110,0,116,0,95,
38220,50,0,1,189, 45960,50,0,1,244,
38231,3,1,6,1, 45971,3,1,6,1,
38245,912,22,1,49, 45985,1034,22,1,80,
38251,1225,913,16,0, 45991,1225,1035,16,0,
3826615,1,1479,914,16, 4600720,1,1479,1036,16,
38270,615,1,1731,915, 46010,720,1,1731,1037,
382816,0,615,1,1989, 460216,0,720,1,1989,
3829916,17,917,15,720, 46031038,17,1039,15,842,
38301,-1,1,5,918, 46041,-1,1,5,1040,
383120,919,4,26,73, 460520,1041,4,26,73,
38320,102,0,83,0, 46060,102,0,83,0,
3833116,0,97,0,116, 4607116,0,97,0,116,
38340,101,0,109,0, 46080,101,0,109,0,
3835101,0,110,0,116, 4609101,0,110,0,116,
38360,95,0,49,0, 46100,95,0,49,0,
38371,184,1,3,1, 46111,239,1,3,1,
38386,1,5,920,22, 46126,1,5,1042,22,
38391,44,1,1990,921, 46131,75,1,1990,1043,
384016,0,615,1,236, 461416,0,720,1,236,
3841922,16,0,615,1, 46151044,16,0,720,1,
38421756,923,16,0,615, 46161756,1045,16,0,720,
38431,4,924,19,184, 46171,4,1046,19,203,
38441,4,925,5,100, 46181,4,1047,5,100,
38451,256,926,16,0, 46191,256,1048,16,0,
3846538,1,1261,927,16, 4620616,1,1261,1049,16,
38470,538,1,509,928, 46210,616,1,509,1050,
384816,0,538,1,1515, 462216,0,616,1,1515,
3849929,16,0,538,1, 46231051,16,0,616,1,
38502021,718,1,1775,930, 46242021,840,1,1775,1052,
385116,0,538,1,2029, 462516,0,616,1,2029,
3852725,1,2030,731,1, 4626847,1,2030,853,1,
38532031,736,1,2032,741, 46272031,858,1,2032,863,
38541,2033,746,1,277, 46281,2033,868,1,277,
3855931,16,0,538,1, 46291053,16,0,616,1,
38562035,752,1,2037,757, 46302035,874,1,2037,879,
38571,2039,762,1,32, 46311,2039,884,1,32,
3858932,16,0,538,1, 46321054,16,0,616,1,
38592041,768,1,2293,933, 46332041,890,1,2293,1055,
386016,0,538,1,2043, 463416,0,616,1,2043,
3861774,1,2045,779,1, 4635896,1,2045,901,1,
386240,934,16,0,186, 463640,1056,16,0,205,
38631,41,935,16,0, 46371,41,1057,16,0,
3864538,1,1297,936,16, 4638616,1,1297,1058,16,
38650,538,1,43,937, 46390,616,1,43,1059,
386616,0,538,1,44, 464016,0,616,1,44,
3867938,16,0,186,1, 46411060,16,0,205,1,
38681803,787,1,1804,939, 46421803,909,1,1804,1061,
386916,0,538,1,299, 464316,0,616,1,299,
3870940,16,0,538,1, 46441062,16,0,616,1,
387147,941,16,0,182, 464547,1063,16,0,201,
38721,52,942,16,0, 46461,52,1064,16,0,
3873538,1,2318,943,16, 4647616,1,2318,1065,16,
38740,538,1,63,944, 46480,616,1,63,1066,
387516,0,201,1,66, 464916,0,227,1,66,
3876945,16,0,199,1, 46501067,16,0,225,1,
38772075,946,16,0,538, 46512075,1068,16,0,616,
38781,1574,799,1,71, 46521,1574,921,1,71,
3879947,16,0,538,1, 46531069,16,0,616,1,
388076,948,16,0,538, 465476,1070,16,0,616,
38811,1834,949,16,0, 46551,1834,1071,16,0,
3882538,1,2337,950,16, 4656616,1,2337,1072,16,
38830,538,1,79,951, 46570,616,1,79,1073,
388416,0,538,1,1335, 465816,0,616,1,1335,
3885952,16,0,538,1, 46591074,16,0,616,1,
3886322,953,16,0,538, 4660322,1075,16,0,616,
38871,85,954,16,0, 46611,85,1076,16,0,
3888538,1,89,955,16, 4662616,1,89,1077,16,
38890,538,1,346,956, 46630,616,1,346,1078,
389016,0,538,1,97, 466416,0,616,1,97,
3891957,16,0,538,1, 46651079,16,0,616,1,
38922106,958,16,0,538, 46662106,1080,16,0,616,
38931,102,959,16,0, 46671,102,1081,16,0,
3894538,1,1860,821,1, 4668616,1,1860,943,1,
38952364,827,1,1114,960, 46692364,949,1,2782,1082,
389616,0,182,1,112, 467016,0,616,1,1114,
3897961,16,0,538,1, 46711083,16,0,201,1,
38981117,962,16,0,538, 4672112,1084,16,0,616,
38991,1873,835,1,1876, 46731,1117,1085,16,0,
3900963,16,0,538,1, 4674616,1,1873,958,1,
3901124,964,16,0,538, 46751876,1086,16,0,616,
39021,2136,842,1,381, 46761,124,1087,16,0,
3903965,16,0,538,1, 4677616,1,2136,965,1,
3904525,966,16,0,538, 4678381,1088,16,0,616,
39051,137,967,16,0, 46791,525,1089,16,0,
3906538,1,1901,968,16, 4680616,1,137,1090,16,
39070,538,1,2658,969, 46810,616,1,1901,1091,
390816,0,538,1,1153, 468216,0,616,1,1153,
3909970,16,0,538,1, 46831092,16,0,616,1,
3910151,971,16,0,538, 4684151,1093,16,0,616,
39111,1407,972,16,0, 46851,1407,1094,16,0,
3912538,1,1659,973,16, 4686616,1,1659,1095,16,
39130,538,1,2413,974, 46870,616,1,2413,1096,
391416,0,538,1,406, 468816,0,616,1,406,
3915975,16,0,538,1, 46891097,16,0,616,1,
39161371,976,16,0,538, 46901371,1098,16,0,616,
39171,2105,814,1,166, 46911,2105,936,1,166,
3918977,16,0,538,1, 46921099,16,0,616,1,
39191622,978,16,0,538, 46931622,1100,16,0,616,
39201,1931,861,1,1933, 46941,1931,983,1,1933,
3921979,16,0,538,1, 46951101,16,0,616,1,
3922431,980,16,0,538, 4696431,1102,16,0,616,
39231,1585,981,16,0, 46971,1585,1103,16,0,
3924538,1,182,982,16, 4698616,1,182,1104,16,
39250,538,1,1189,983, 46990,616,1,1189,1105,
392616,0,538,1,1443, 470016,0,616,1,1443,
3927984,16,0,538,1, 47011106,16,0,616,1,
39281695,985,16,0,538, 47021695,1107,16,0,616,
39291,2198,986,16,0, 47031,2198,1108,16,0,
3930538,1,447,987,16, 4704616,1,447,1109,16,
39310,538,1,2458,876, 47050,616,1,2458,998,
39321,2459,882,1,1958, 47061,2459,1004,1,1958,
3933988,16,0,538,1, 47071110,16,0,616,1,
39342462,889,1,1657,894, 47082462,1011,1,1657,1016,
39351,2464,899,1,199, 47091,2464,1021,1,199,
3936989,16,0,538,1, 47101111,16,0,616,1,
3937459,990,16,0,538, 4711459,1112,16,0,616,
39381,462,991,16,0, 47121,462,1113,16,0,
3939538,1,217,992,16, 4713616,1,217,1114,16,
39400,538,1,2227,908, 47140,616,1,2227,1030,
39411,1225,993,16,0, 47151,1225,1115,16,0,
3942538,1,1479,994,16, 4716616,1,1479,1116,16,
39430,538,1,1731,995, 47170,616,1,1731,1117,
394416,0,538,1,1989, 471816,0,616,1,1989,
3945916,1,1990,996,16, 47191038,1,1990,1118,16,
39460,538,1,236,997, 47200,616,1,236,1119,
394716,0,538,1,1756, 472116,0,616,1,1756,
3948998,16,0,538,1, 47221120,16,0,616,1,
39495,999,19,181,1, 47235,1121,19,200,1,
39505,1000,5,100,1, 47245,1122,5,100,1,
3951256,1001,16,0,534, 4725256,1123,16,0,612,
39521,1261,1002,16,0, 47261,1261,1124,16,0,
3953534,1,509,1003,16, 4727612,1,509,1125,16,
39540,534,1,1515,1004, 47280,612,1,1515,1126,
395516,0,534,1,2021, 472916,0,612,1,2021,
3956718,1,1775,1005,16, 4730840,1,1775,1127,16,
39570,534,1,2029,725, 47310,612,1,2029,847,
39581,2030,731,1,2031, 47321,2030,853,1,2031,
3959736,1,2032,741,1, 4733858,1,2032,863,1,
39602033,746,1,277,1006, 47342033,868,1,277,1128,
396116,0,534,1,2035, 473516,0,612,1,2035,
3962752,1,2037,757,1, 4736874,1,2037,879,1,
39632039,762,1,32,1007, 47372039,884,1,32,1129,
396416,0,534,1,2041, 473816,0,612,1,2041,
3965768,1,2293,1008,16, 4739890,1,2293,1130,16,
39660,534,1,2043,774, 47400,612,1,2043,896,
39671,2045,779,1,40, 47411,2045,901,1,40,
39681009,16,0,185,1, 47421131,16,0,204,1,
396941,1010,16,0,534, 474341,1132,16,0,612,
39701,1297,1011,16,0, 47441,1297,1133,16,0,
3971534,1,43,1012,16, 4745612,1,43,1134,16,
39720,534,1,44,1013, 47460,612,1,44,1135,
397316,0,185,1,1803, 474716,0,204,1,1803,
3974787,1,1804,1014,16, 4748909,1,1804,1136,16,
39750,534,1,299,1015, 47490,612,1,299,1137,
397616,0,534,1,47, 475016,0,612,1,47,
39771016,16,0,179,1, 47511138,16,0,198,1,
397852,1017,16,0,534, 475252,1139,16,0,612,
39791,2318,1018,16,0, 47531,2318,1140,16,0,
3980534,1,63,1019,16, 4754612,1,63,1141,16,
39810,200,1,66,1020, 47550,226,1,66,1142,
398216,0,198,1,2075, 475616,0,224,1,2075,
39831021,16,0,534,1, 47571143,16,0,612,1,
39841574,799,1,71,1022, 47581574,921,1,71,1144,
398516,0,534,1,76, 475916,0,612,1,76,
39861023,16,0,534,1, 47601145,16,0,612,1,
39871834,1024,16,0,534, 47611834,1146,16,0,612,
39881,2337,1025,16,0, 47621,2337,1147,16,0,
3989534,1,79,1026,16, 4763612,1,79,1148,16,
39900,534,1,1335,1027, 47640,612,1,1335,1149,
399116,0,534,1,322, 476516,0,612,1,322,
39921028,16,0,534,1, 47661150,16,0,612,1,
399385,1029,16,0,534, 476785,1151,16,0,612,
39941,89,1030,16,0, 47681,89,1152,16,0,
3995534,1,346,1031,16, 4769612,1,346,1153,16,
39960,534,1,97,1032, 47700,612,1,97,1154,
399716,0,534,1,2106, 477116,0,612,1,2106,
39981033,16,0,534,1, 47721155,16,0,612,1,
3999102,1034,16,0,534, 4773102,1156,16,0,612,
40001,1860,821,1,2364, 47741,1860,943,1,2364,
4001827,1,1114,1035,16, 4775949,1,2782,1157,16,
40020,179,1,112,1036, 47760,612,1,1114,1158,
400316,0,534,1,1117, 477716,0,198,1,112,
40041037,16,0,534,1, 47781159,16,0,612,1,
40051873,835,1,1876,1038, 47791117,1160,16,0,612,
400616,0,534,1,124, 47801,1873,958,1,1876,
40071039,16,0,534,1, 47811161,16,0,612,1,
40082136,842,1,381,1040, 4782124,1162,16,0,612,
400916,0,534,1,525, 47831,2136,965,1,381,
40101041,16,0,534,1, 47841163,16,0,612,1,
4011137,1042,16,0,534, 4785525,1164,16,0,612,
40121,1901,1043,16,0, 47861,137,1165,16,0,
4013534,1,2658,1044,16, 4787612,1,1901,1166,16,
40140,534,1,1153,1045, 47880,612,1,1153,1167,
401516,0,534,1,151, 478916,0,612,1,151,
40161046,16,0,534,1, 47901168,16,0,612,1,
40171407,1047,16,0,534, 47911407,1169,16,0,612,
40181,1659,1048,16,0, 47921,1659,1170,16,0,
4019534,1,2413,1049,16, 4793612,1,2413,1171,16,
40200,534,1,406,1050, 47940,612,1,406,1172,
402116,0,534,1,1371, 479516,0,612,1,1371,
40221051,16,0,534,1, 47961173,16,0,612,1,
40232105,814,1,166,1052, 47972105,936,1,166,1174,
402416,0,534,1,1622, 479816,0,612,1,1622,
40251053,16,0,534,1, 47991175,16,0,612,1,
40261931,861,1,1933,1054, 48001931,983,1,1933,1176,
402716,0,534,1,431, 480116,0,612,1,431,
40281055,16,0,534,1, 48021177,16,0,612,1,
40291585,1056,16,0,534, 48031585,1178,16,0,612,
40301,182,1057,16,0, 48041,182,1179,16,0,
4031534,1,1189,1058,16, 4805612,1,1189,1180,16,
40320,534,1,1443,1059, 48060,612,1,1443,1181,
403316,0,534,1,1695, 480716,0,612,1,1695,
40341060,16,0,534,1, 48081182,16,0,612,1,
40352198,1061,16,0,534, 48092198,1183,16,0,612,
40361,447,1062,16,0, 48101,447,1184,16,0,
4037534,1,2458,876,1, 4811612,1,2458,998,1,
40382459,882,1,1958,1063, 48122459,1004,1,1958,1185,
403916,0,534,1,2462, 481316,0,612,1,2462,
4040889,1,1657,894,1, 48141011,1,1657,1016,1,
40412464,899,1,199,1064, 48152464,1021,1,199,1186,
404216,0,534,1,459, 481616,0,612,1,459,
40431065,16,0,534,1, 48171187,16,0,612,1,
4044462,1066,16,0,534, 4818462,1188,16,0,612,
40451,217,1067,16,0, 48191,217,1189,16,0,
4046534,1,2227,908,1, 4820612,1,2227,1030,1,
40471225,1068,16,0,534, 48211225,1190,16,0,612,
40481,1479,1069,16,0, 48221,1479,1191,16,0,
4049534,1,1731,1070,16, 4823612,1,1731,1192,16,
40500,534,1,1989,916, 48240,612,1,1989,1038,
40511,1990,1071,16,0, 48251,1990,1193,16,0,
4052534,1,236,1072,16, 4826612,1,236,1194,16,
40530,534,1,1756,1073, 48270,612,1,1756,1195,
405416,0,534,1,6, 482816,0,612,1,6,
40551074,19,277,1,6, 48291196,19,306,1,6,
40561075,5,2,1,1114, 48301197,5,2,1,1114,
40571076,16,0,275,1, 48311198,16,0,304,1,
405840,1077,16,0,523, 483240,1199,16,0,601,
40591,7,1078,19,243, 48331,7,1200,19,270,
40601,7,1079,5,2, 48341,7,1201,5,2,
40611,1114,1080,16,0, 48351,1114,1202,16,0,
4062241,1,40,1081,16, 4836268,1,40,1203,16,
40630,459,1,8,1082, 48370,531,1,8,1204,
406419,207,1,8,1083, 483819,233,1,8,1205,
40655,2,1,1114,1084, 48395,2,1,1114,1206,
406616,0,205,1,40, 484016,0,231,1,40,
40671085,16,0,439,1, 48411207,16,0,489,1,
40689,1086,19,213,1, 48429,1208,19,239,1,
40699,1087,5,2,1, 48439,1209,5,2,1,
40701114,1088,16,0,211, 48441114,1210,16,0,237,
40711,40,1089,16,0, 48451,40,1211,16,0,
4072384,1,10,1090,19, 4846420,1,10,1212,19,
4073164,1,10,1091,5, 4847183,1,10,1213,5,
40742,1,1114,1092,16, 48482,1,1114,1214,16,
40750,162,1,40,1093, 48490,181,1,40,1215,
407616,0,324,1,11, 485016,0,360,1,11,
40771094,19,192,1,11, 48511216,19,147,1,11,
40781095,5,146,1,1260, 48521217,5,146,1,1260,
40791096,17,1097,15,1098, 48531218,17,1219,15,1220,
40804,34,37,0,83, 48544,34,37,0,83,
40810,105,0,109,0, 48550,105,0,109,0,
4082112,0,108,0,101, 4856112,0,108,0,101,
@@ -4085,7 +4859,7 @@ public yyLSLSyntax
40850,110,0,109,0, 48590,110,0,109,0,
4086101,0,110,0,116, 4860101,0,110,0,116,
40870,1,-1,1,5, 48610,1,-1,1,5,
40881099,20,1100,4,38, 48621221,20,1222,4,38,
408983,0,105,0,109, 486383,0,105,0,109,
40900,112,0,108,0, 48640,112,0,108,0,
4091101,0,65,0,115, 4865101,0,65,0,115,
@@ -4093,11 +4867,11 @@ public yyLSLSyntax
4093103,0,110,0,109, 4867103,0,110,0,109,
40940,101,0,110,0, 48680,101,0,110,0,
4095116,0,95,0,50, 4869116,0,95,0,50,
40960,49,0,1,220, 48700,49,0,1,275,
40971,3,1,6,1, 48711,3,1,6,1,
40985,1101,22,1,80, 48725,1223,22,1,111,
40991,1011,1102,17,1103, 48731,1011,1224,17,1225,
410015,1104,4,44,37, 487415,1226,4,44,37,
41010,80,0,97,0, 48750,80,0,97,0,
4102114,0,101,0,110, 4876114,0,101,0,110,
41030,116,0,104,0, 48770,116,0,104,0,
@@ -4107,7 +4881,7 @@ public yyLSLSyntax
41070,101,0,115,0, 48810,101,0,115,0,
4108115,0,105,0,111, 4882115,0,105,0,111,
41090,110,0,1,-1, 48830,110,0,1,-1,
41101,5,1105,20,1106, 48841,5,1227,20,1228,
41114,46,80,0,97, 48854,46,80,0,97,
41120,114,0,101,0, 48860,114,0,101,0,
4113110,0,116,0,104, 4887110,0,116,0,104,
@@ -4117,12 +4891,12 @@ public yyLSLSyntax
4117114,0,101,0,115, 4891114,0,101,0,115,
41180,115,0,105,0, 48920,115,0,105,0,
4119111,0,110,0,95, 4893111,0,110,0,95,
41200,50,0,1,267, 48940,50,0,1,322,
41211,3,1,4,1, 48951,3,1,4,1,
41223,1107,22,1,127, 48963,1229,22,1,158,
41231,1514,1108,17,1109, 48971,1514,1230,17,1231,
412415,1098,1,-1,1, 489815,1220,1,-1,1,
41255,1110,20,1111,4, 48995,1232,20,1233,4,
412638,83,0,105,0, 490038,83,0,105,0,
4127109,0,112,0,108, 4901109,0,112,0,108,
41280,101,0,65,0, 49020,101,0,65,0,
@@ -4131,26 +4905,26 @@ public yyLSLSyntax
4131109,0,101,0,110, 4905109,0,101,0,110,
41320,116,0,95,0, 49060,116,0,95,0,
413349,0,52,0,1, 490749,0,52,0,1,
4134213,1,3,1,4, 4908268,1,3,1,4,
41351,3,1112,22,1, 49091,3,1234,22,1,
413673,1,9,1113,17, 4910104,1,9,1235,17,
41371114,15,1115,4,24, 49111236,15,1237,4,24,
413837,0,68,0,101, 491237,0,68,0,101,
41390,99,0,108,0, 49130,99,0,108,0,
414097,0,114,0,97, 491497,0,114,0,97,
41410,116,0,105,0, 49150,116,0,105,0,
4142111,0,110,0,1, 4916111,0,110,0,1,
4143-1,1,5,1116,20, 4917-1,1,5,1238,20,
41441117,4,26,68,0, 49181239,4,26,68,0,
4145101,0,99,0,108, 4919101,0,99,0,108,
41460,97,0,114,0, 49200,97,0,114,0,
414797,0,116,0,105, 492197,0,116,0,105,
41480,111,0,110,0, 49220,111,0,110,0,
414995,0,49,0,1, 492395,0,49,0,1,
4150161,1,3,1,3, 4924212,1,3,1,3,
41511,2,1118,22,1, 49251,2,1240,22,1,
415221,1,262,1119,17, 492648,1,262,1241,17,
41531120,15,1121,4,34, 49271242,15,1243,4,34,
415437,0,66,0,105, 492837,0,66,0,105,
41550,110,0,97,0, 49290,110,0,97,0,
4156114,0,121,0,69, 4930114,0,121,0,69,
@@ -4158,8 +4932,8 @@ public yyLSLSyntax
4158114,0,101,0,115, 4932114,0,101,0,115,
41590,115,0,105,0, 49330,115,0,105,0,
4160111,0,110,0,1, 4934111,0,110,0,1,
4161-1,1,5,1122,20, 4935-1,1,5,1244,20,
41621123,4,36,66,0, 49361245,4,36,66,0,
4163105,0,110,0,97, 4937105,0,110,0,97,
41640,114,0,121,0, 49380,114,0,121,0,
416569,0,120,0,112, 493969,0,120,0,112,
@@ -4167,11 +4941,11 @@ public yyLSLSyntax
4167115,0,115,0,105, 4941115,0,115,0,105,
41680,111,0,110,0, 49420,111,0,110,0,
416995,0,53,0,1, 494395,0,53,0,1,
4170249,1,3,1,4, 4944304,1,3,1,4,
41711,3,1124,22,1, 49451,3,1246,22,1,
4172109,1,1267,1125,17, 4946140,1,1267,1247,17,
41731126,15,1098,1,-1, 49471248,15,1220,1,-1,
41741,5,1127,20,1128, 49481,5,1249,20,1250,
41754,36,83,0,105, 49494,36,83,0,105,
41760,109,0,112,0, 49500,109,0,112,0,
4177108,0,101,0,65, 4951108,0,101,0,65,
@@ -4179,13 +4953,13 @@ public yyLSLSyntax
4179105,0,103,0,110, 4953105,0,103,0,110,
41800,109,0,101,0, 49540,109,0,101,0,
4181110,0,116,0,95, 4955110,0,116,0,95,
41820,56,0,1,207, 49560,56,0,1,262,
41831,3,1,6,1, 49571,3,1,6,1,
41845,1129,22,1,67, 49585,1251,22,1,98,
41851,2021,718,1,1521, 49591,2021,840,1,1521,
41861130,17,1131,15,1098, 49601252,17,1253,15,1220,
41871,-1,1,5,1132, 49611,-1,1,5,1254,
418820,1133,4,36,83, 496220,1255,4,36,83,
41890,105,0,109,0, 49630,105,0,109,0,
4190112,0,108,0,101, 4964112,0,108,0,101,
41910,65,0,115,0, 49650,65,0,115,0,
@@ -4193,26 +4967,26 @@ public yyLSLSyntax
41930,110,0,109,0, 49670,110,0,109,0,
4194101,0,110,0,116, 4968101,0,110,0,116,
41950,95,0,49,0, 49690,95,0,49,0,
41961,200,1,3,1, 49701,255,1,3,1,
41974,1,3,1134,22, 49714,1,3,1256,22,
41981,60,1,2024,1135, 49721,91,1,2024,1257,
419917,1136,15,1137,4, 497317,1258,15,1259,4,
420024,37,0,83,0, 497424,37,0,83,0,
4201116,0,97,0,116, 4975116,0,97,0,116,
42020,101,0,67,0, 49760,101,0,67,0,
4203104,0,97,0,110, 4977104,0,97,0,110,
42040,103,0,101,0, 49780,103,0,101,0,
42051,-1,1,5,1138, 49791,-1,1,5,1260,
420620,1139,4,26,83, 498020,1261,4,26,83,
42070,116,0,97,0, 49810,116,0,97,0,
4208116,0,101,0,67, 4982116,0,101,0,67,
42090,104,0,97,0, 49830,104,0,97,0,
4210110,0,103,0,101, 4984110,0,103,0,101,
42110,95,0,49,0, 49850,95,0,49,0,
42121,182,1,3,1, 49861,237,1,3,1,
42133,1,2,1140,22, 49873,1,2,1262,22,
42141,42,1,1775,1141, 49881,73,1,1775,1263,
421517,1142,15,1143,4, 498917,1264,15,1265,4,
421630,37,0,69,0, 499030,37,0,69,0,
4217109,0,112,0,116, 4991109,0,112,0,116,
42180,121,0,83,0, 49920,121,0,83,0,
@@ -4220,34 +4994,34 @@ public yyLSLSyntax
42200,101,0,109,0, 49940,101,0,109,0,
4221101,0,110,0,116, 4995101,0,110,0,116,
42220,1,-1,1,5, 49960,1,-1,1,5,
42231144,20,1145,4,32, 49971266,20,1267,4,32,
422469,0,109,0,112, 499869,0,109,0,112,
42250,116,0,121,0, 49990,116,0,121,0,
422683,0,116,0,97, 500083,0,116,0,97,
42270,116,0,101,0, 50010,116,0,101,0,
4228109,0,101,0,110, 5002109,0,101,0,110,
42290,116,0,95,0, 50030,116,0,95,0,
423049,0,1,166,1, 500449,0,1,221,1,
42313,1,1,1,0, 50053,1,1,1,0,
42321146,22,1,26,1, 50061268,22,1,57,1,
423319,1147,17,1114,1, 500719,1269,17,1236,1,
42342,1118,1,2028,1148, 50082,1240,1,2028,1270,
423517,1149,15,1150,4, 500917,1271,15,1272,4,
423620,37,0,74,0, 501020,37,0,74,0,
4237117,0,109,0,112, 5011117,0,109,0,112,
42380,76,0,97,0, 50120,76,0,97,0,
423998,0,101,0,108, 501398,0,101,0,108,
42400,1,-1,1,5, 50140,1,-1,1,5,
42411151,20,1152,4,22, 50151273,20,1274,4,22,
424274,0,117,0,109, 501674,0,117,0,109,
42430,112,0,76,0, 50170,112,0,76,0,
424497,0,98,0,101, 501897,0,98,0,101,
42450,108,0,95,0, 50190,108,0,95,0,
424649,0,1,180,1, 502049,0,1,235,1,
42473,1,3,1,2, 50213,1,3,1,2,
42481153,22,1,40,1, 50221275,22,1,71,1,
42492029,725,1,2281,1154, 50232029,847,1,2281,1276,
425017,1155,15,1156,4, 502417,1277,15,1278,4,
425134,37,0,70,0, 502534,37,0,70,0,
4252111,0,114,0,76, 5026111,0,114,0,76,
42530,111,0,111,0, 50270,111,0,111,0,
@@ -4255,8 +5029,8 @@ public yyLSLSyntax
42550,97,0,116,0, 50290,97,0,116,0,
4256101,0,109,0,101, 5030101,0,109,0,101,
42570,110,0,116,0, 50310,110,0,116,0,
42581,-1,1,5,1157, 50321,-1,1,5,1279,
425920,1158,4,36,70, 503320,1280,4,36,70,
42600,111,0,114,0, 50340,111,0,114,0,
426176,0,111,0,111, 503576,0,111,0,111,
42620,112,0,83,0, 50360,112,0,83,0,
@@ -4264,124 +5038,107 @@ public yyLSLSyntax
42640,101,0,109,0, 50380,101,0,109,0,
4265101,0,110,0,116, 5039101,0,110,0,116,
42660,95,0,50,0, 50400,95,0,50,0,
42671,195,1,3,1, 50411,250,1,3,1,
42682,1,1,1159,22, 50422,1,1,1281,22,
42691,55,1,2031,736, 50431,86,1,2031,858,
42701,2032,741,1,2033, 50441,2032,863,1,2033,
4271746,1,2034,1160,16, 5045868,1,2034,1282,16,
42720,572,1,2035,752, 50460,676,1,2788,1283,
42731,2036,1161,16,0, 504716,0,145,1,2036,
4274524,1,2037,757,1, 50481284,16,0,602,1,
42752038,1162,16,0,528, 50492037,879,1,2038,1285,
42761,2039,762,1,32, 505016,0,606,1,2039,
42771163,17,1142,1,0, 5051884,1,32,1286,17,
42781146,1,2041,768,1, 50521264,1,0,1268,1,
42792042,1164,16,0,646, 50532041,890,1,2042,1287,
42801,2043,774,1,2044, 505416,0,749,1,2043,
42811165,16,0,584,1, 5055896,1,2044,1288,16,
42822045,779,1,2299,1166, 50560,689,1,2045,901,
428316,0,226,1,1296, 50571,2299,1289,16,0,
42841167,17,1168,15,1098, 5058255,1,1296,1290,17,
42851,-1,1,5,1169, 50591291,15,1220,1,-1,
428620,1170,4,38,83, 50601,5,1292,20,1293,
42870,105,0,109,0, 50614,38,83,0,105,
4288112,0,108,0,101, 50620,109,0,112,0,
42890,65,0,115,0, 5063108,0,101,0,65,
4290115,0,105,0,103, 50640,115,0,115,0,
42910,110,0,109,0, 5065105,0,103,0,110,
4292101,0,110,0,116, 50660,109,0,101,0,
42930,95,0,50,0, 5067110,0,116,0,95,
429448,0,1,219,1, 50680,50,0,48,0,
42953,1,6,1,5, 50691,274,1,3,1,
42961171,22,1,79,1, 50706,1,5,1294,22,
4297283,1172,17,1173,15, 50711,110,1,283,1295,
42981121,1,-1,1,5, 507217,1296,15,1243,1,
42991174,20,1175,4,36, 5073-1,1,5,1297,20,
430066,0,105,0,110, 50741298,4,36,66,0,
43010,97,0,114,0, 5075105,0,110,0,97,
4302121,0,69,0,120, 50760,114,0,121,0,
43030,112,0,114,0, 507769,0,120,0,112,
4304101,0,115,0,115, 50780,114,0,101,0,
43050,105,0,111,0, 5079115,0,115,0,105,
4306110,0,95,0,52, 50800,111,0,110,0,
43070,1,248,1,3, 508195,0,52,0,1,
43081,4,1,3,1176, 5082303,1,3,1,4,
430922,1,108,1,40, 50831,3,1299,22,1,
43101177,17,1178,15,1179, 5084139,1,40,1300,17,
43114,32,37,0,73, 50851301,15,1302,4,32,
43120,100,0,101,0, 508637,0,73,0,100,
4313110,0,116,0,69, 50870,101,0,110,0,
43140,120,0,112,0,
4315114,0,101,0,115,
43160,115,0,105,0,
4317111,0,110,0,1,
4318-1,1,5,1180,20,
43191181,4,34,73,0,
4320100,0,101,0,110,
43210,116,0,69,0,
4322120,0,112,0,114,
43230,101,0,115,0,
4324115,0,105,0,111,
43250,110,0,95,0,
432649,0,1,234,1,
43273,1,2,1,1,
43281182,22,1,94,1,
432944,1183,17,1178,1,
43301,1182,1,1803,787,
43311,47,1184,17,1185,
433215,1186,4,38,37,
43330,73,0,100,0,
4334101,0,110,0,116,
43350,68,0,111,0,
4336116,0,69,0,120, 5088116,0,69,0,120,
43370,112,0,114,0, 50890,112,0,114,0,
4338101,0,115,0,115, 5090101,0,115,0,115,
43390,105,0,111,0, 50910,105,0,111,0,
4340110,0,1,-1,1, 5092110,0,1,-1,1,
43415,1187,20,1188,4, 50935,1303,20,1304,4,
434240,73,0,100,0, 509434,73,0,100,0,
4343101,0,110,0,116, 5095101,0,110,0,116,
43440,68,0,111,0, 50960,69,0,120,0,
4345116,0,69,0,120, 5097112,0,114,0,101,
43460,112,0,114,0, 50980,115,0,115,0,
4347101,0,115,0,115, 5099105,0,111,0,110,
43480,105,0,111,0, 51000,95,0,49,0,
4349110,0,95,0,49, 51011,289,1,3,1,
43500,1,235,1,3, 51022,1,1,1305,22,
43511,4,1,3,1189, 51031,125,1,44,1306,
435222,1,95,1,48, 510417,1301,1,1,1305,
43531190,17,1191,15,1192, 51051,1803,909,1,47,
43544,58,37,0,73, 51061307,17,1308,15,1309,
43550,110,0,99,0, 51074,38,37,0,73,
4356114,0,101,0,109, 51080,100,0,101,0,
43570,101,0,110,0, 5109110,0,116,0,68,
4358116,0,68,0,101, 51100,111,0,116,0,
43590,99,0,114,0,
4360101,0,109,0,101,
43610,110,0,116,0,
436269,0,120,0,112, 511169,0,120,0,112,
43630,114,0,101,0, 51120,114,0,101,0,
4364115,0,115,0,105, 5113115,0,115,0,105,
43650,111,0,110,0, 51140,111,0,110,0,
43661,-1,1,5,1193, 51151,-1,1,5,1310,
436720,1194,4,60,73, 511620,1311,4,40,73,
43680,110,0,99,0, 51170,100,0,101,0,
4369114,0,101,0,109, 5118110,0,116,0,68,
43700,101,0,110,0, 51190,111,0,116,0,
4371116,0,68,0,101,
43720,99,0,114,0,
4373101,0,109,0,101,
43740,110,0,116,0,
437569,0,120,0,112, 512069,0,120,0,112,
43760,114,0,101,0, 51210,114,0,101,0,
4377115,0,115,0,105, 5122115,0,115,0,105,
43780,111,0,110,0, 51230,111,0,110,0,
437995,0,52,0,1, 512495,0,49,0,1,
4380239,1,3,1,5, 5125290,1,3,1,4,
43811,4,1195,22,1, 51261,3,1312,22,1,
438299,1,49,1196,17, 5127126,1,48,1313,17,
43831197,15,1192,1,-1, 51281314,15,1315,4,58,
43841,5,1198,20,1199, 512937,0,73,0,110,
51300,99,0,114,0,
5131101,0,109,0,101,
51320,110,0,116,0,
513368,0,101,0,99,
51340,114,0,101,0,
5135109,0,101,0,110,
51360,116,0,69,0,
5137120,0,112,0,114,
51380,101,0,115,0,
5139115,0,105,0,111,
51400,110,0,1,-1,
51411,5,1316,20,1317,
43854,60,73,0,110, 51424,60,73,0,110,
43860,99,0,114,0, 51430,99,0,114,0,
4387101,0,109,0,101, 5144101,0,109,0,101,
@@ -4394,12 +5151,12 @@ public yyLSLSyntax
43940,101,0,115,0, 51510,101,0,115,0,
4395115,0,105,0,111, 5152115,0,105,0,111,
43960,110,0,95,0, 51530,110,0,95,0,
439751,0,1,238,1, 515452,0,1,294,1,
43983,1,5,1,4, 51553,1,5,1,4,
43991200,22,1,98,1, 51561318,22,1,130,1,
440050,1201,17,1202,15, 515749,1319,17,1320,15,
44011192,1,-1,1,5, 51581315,1,-1,1,5,
44021203,20,1204,4,60, 51591321,20,1322,4,60,
440373,0,110,0,99, 516073,0,110,0,99,
44040,114,0,101,0, 51610,114,0,101,0,
4405109,0,101,0,110, 5162109,0,101,0,110,
@@ -4411,13 +5168,13 @@ public yyLSLSyntax
4411112,0,114,0,101, 5168112,0,114,0,101,
44120,115,0,115,0, 51690,115,0,115,0,
4413105,0,111,0,110, 5170105,0,111,0,110,
44140,95,0,50,0, 51710,95,0,51,0,
44151,237,1,3,1, 51721,293,1,3,1,
44163,1,2,1205,22, 51735,1,4,1323,22,
44171,97,1,51,1206, 51741,129,1,50,1324,
441817,1207,15,1192,1, 517517,1325,15,1315,1,
4419-1,1,5,1208,20, 5176-1,1,5,1326,20,
44201209,4,60,73,0, 51771327,4,60,73,0,
4421110,0,99,0,114, 5178110,0,99,0,114,
44220,101,0,109,0, 51790,101,0,109,0,
4423101,0,110,0,116, 5180101,0,110,0,116,
@@ -4429,67 +5186,71 @@ public yyLSLSyntax
4429114,0,101,0,115, 5186114,0,101,0,115,
44300,115,0,105,0, 51870,115,0,105,0,
4431111,0,110,0,95, 5188111,0,110,0,95,
44320,49,0,1,236, 51890,50,0,1,292,
44331,3,1,3,1, 51901,3,1,3,1,
44342,1210,22,1,96, 51912,1328,22,1,128,
44351,305,1211,17,1212, 51921,51,1329,17,1330,
443615,1121,1,-1,1, 519315,1315,1,-1,1,
44375,1213,20,1214,4, 51945,1331,20,1332,4,
443836,66,0,105,0, 519560,73,0,110,0,
4439110,0,97,0,114, 519699,0,114,0,101,
44400,121,0,69,0, 51970,109,0,101,0,
4441120,0,112,0,114, 5198110,0,116,0,68,
44420,101,0,115,0,
4443115,0,105,0,111,
44440,110,0,95,0,
444551,0,1,247,1,
44463,1,4,1,3,
44471215,22,1,107,1,
4448525,1216,17,1217,15,
44491218,4,34,37,0,
445082,0,111,0,116,
44510,97,0,116,0,
4452105,0,111,0,110,
44530,67,0,111,0,
4454110,0,115,0,116,
44550,97,0,110,0,
4456116,0,1,-1,1,
44575,1219,20,1220,4,
445836,82,0,111,0,
4459116,0,97,0,116,
44600,105,0,111,0,
4461110,0,67,0,111,
44620,110,0,115,0,
4463116,0,97,0,110,
44640,116,0,95,0,
446549,0,1,232,1,
44663,1,10,1,9,
44671221,22,1,92,1,
446863,1222,17,1223,15,
44691224,4,38,37,0,
447084,0,121,0,112,
44710,101,0,99,0,
447297,0,115,0,116,
44730,69,0,120,0,
4474112,0,114,0,101,
44750,115,0,115,0,
4476105,0,111,0,110,
44770,1,-1,1,5,
44781225,20,1226,4,40,
447984,0,121,0,112,
44800,101,0,99,0, 51990,101,0,99,0,
448197,0,115,0,116, 5200114,0,101,0,109,
52010,101,0,110,0,
5202116,0,69,0,120,
52030,112,0,114,0,
5204101,0,115,0,115,
52050,105,0,111,0,
5206110,0,95,0,49,
52070,1,291,1,3,
52081,3,1,2,1333,
520922,1,127,1,305,
52101334,17,1335,15,1243,
52111,-1,1,5,1336,
521220,1337,4,36,66,
52130,105,0,110,0,
521497,0,114,0,121,
44820,69,0,120,0, 52150,69,0,120,0,
4483112,0,114,0,101, 5216112,0,114,0,101,
44840,115,0,115,0, 52170,115,0,115,0,
4485105,0,111,0,110, 5218105,0,111,0,110,
44860,95,0,50,0, 52190,95,0,51,0,
44871,269,1,3,1, 52201,302,1,3,1,
44885,1,4,1227,22, 52214,1,3,1338,22,
44891,129,1,66,1228, 52221,138,1,525,1339,
449017,1229,15,1224,1, 522317,1340,15,1341,4,
4491-1,1,5,1230,20, 522434,37,0,82,0,
44921231,4,40,84,0, 5225111,0,116,0,97,
52260,116,0,105,0,
5227111,0,110,0,67,
52280,111,0,110,0,
5229115,0,116,0,97,
52300,110,0,116,0,
52311,-1,1,5,1342,
523220,1343,4,36,82,
52330,111,0,116,0,
523497,0,116,0,105,
52350,111,0,110,0,
523667,0,111,0,110,
52370,115,0,116,0,
523897,0,110,0,116,
52390,95,0,49,0,
52401,287,1,3,1,
524110,1,9,1344,22,
52421,123,1,63,1345,
524317,1346,15,1347,4,
524438,37,0,84,0,
5245121,0,112,0,101,
52460,99,0,97,0,
5247115,0,116,0,69,
52480,120,0,112,0,
5249114,0,101,0,115,
52500,115,0,105,0,
5251111,0,110,0,1,
5252-1,1,5,1348,20,
52531349,4,40,84,0,
4493121,0,112,0,101, 5254121,0,112,0,101,
44940,99,0,97,0, 52550,99,0,97,0,
4495115,0,116,0,69, 5256115,0,116,0,69,
@@ -4497,12 +5258,12 @@ public yyLSLSyntax
4497114,0,101,0,115, 5258114,0,101,0,115,
44980,115,0,105,0, 52590,115,0,105,0,
4499111,0,110,0,95, 5260111,0,110,0,95,
45000,51,0,1,270, 52610,50,0,1,324,
45011,3,1,7,1, 52621,3,1,5,1,
45026,1232,22,1,130, 52634,1350,22,1,160,
45031,67,1233,17,1234, 52641,66,1351,17,1352,
450415,1224,1,-1,1, 526515,1347,1,-1,1,
45055,1235,20,1236,4, 52665,1353,20,1354,4,
450640,84,0,121,0, 526740,84,0,121,0,
4507112,0,101,0,99, 5268112,0,101,0,99,
45080,97,0,115,0, 52690,97,0,115,0,
@@ -4510,13 +5271,13 @@ public yyLSLSyntax
45100,112,0,114,0, 52710,112,0,114,0,
4511101,0,115,0,115, 5272101,0,115,0,115,
45120,105,0,111,0, 52730,105,0,111,0,
4513110,0,95,0,55, 5274110,0,95,0,51,
45140,1,274,1,3, 52750,1,325,1,3,
45151,8,1,7,1237, 52761,7,1,6,1355,
451622,1,134,1,68, 527722,1,161,1,67,
45171238,17,1239,15,1224, 52781356,17,1357,15,1347,
45181,-1,1,5,1240, 52791,-1,1,5,1358,
451920,1241,4,40,84, 528020,1359,4,40,84,
45200,121,0,112,0, 52810,121,0,112,0,
4521101,0,99,0,97, 5282101,0,99,0,97,
45220,115,0,116,0, 52830,115,0,116,0,
@@ -4524,12 +5285,12 @@ public yyLSLSyntax
45240,114,0,101,0, 52850,114,0,101,0,
4525115,0,115,0,105, 5286115,0,115,0,105,
45260,111,0,110,0, 52870,111,0,110,0,
452795,0,53,0,1, 528895,0,55,0,1,
4528272,1,3,1,8, 5289329,1,3,1,8,
45291,7,1242,22,1, 52901,7,1360,22,1,
4530132,1,69,1243,17, 5291165,1,68,1361,17,
45311244,15,1224,1,-1, 52921362,15,1347,1,-1,
45321,5,1245,20,1246, 52931,5,1363,20,1364,
45334,40,84,0,121, 52944,40,84,0,121,
45340,112,0,101,0, 52950,112,0,101,0,
453599,0,97,0,115, 529699,0,97,0,115,
@@ -4538,12 +5299,12 @@ public yyLSLSyntax
45380,101,0,115,0, 52990,101,0,115,0,
4539115,0,105,0,111, 5300115,0,105,0,111,
45400,110,0,95,0, 53010,110,0,95,0,
454154,0,1,273,1, 530253,0,1,327,1,
45423,1,6,1,5, 53033,1,8,1,7,
45431247,22,1,133,1, 53041365,22,1,163,1,
454470,1248,17,1249,15, 530569,1366,17,1367,15,
45451224,1,-1,1,5, 53061347,1,-1,1,5,
45461250,20,1251,4,40, 53071368,20,1369,4,40,
454784,0,121,0,112, 530884,0,121,0,112,
45480,101,0,99,0, 53090,101,0,99,0,
454997,0,115,0,116, 531097,0,115,0,116,
@@ -4551,13 +5312,13 @@ public yyLSLSyntax
4551112,0,114,0,101, 5312112,0,114,0,101,
45520,115,0,115,0, 53130,115,0,115,0,
4553105,0,111,0,110, 5314105,0,111,0,110,
45540,95,0,52,0, 53150,95,0,54,0,
45551,271,1,3,1, 53161,328,1,3,1,
45566,1,5,1252,22, 53176,1,5,1370,22,
45571,131,1,74,1253, 53181,164,1,70,1371,
455817,1254,15,1224,1, 531917,1372,15,1347,1,
4559-1,1,5,1255,20, 5320-1,1,5,1373,20,
45601256,4,40,84,0, 53211374,4,40,84,0,
4561121,0,112,0,101, 5322121,0,112,0,101,
45620,99,0,97,0, 53230,99,0,97,0,
4563115,0,116,0,69, 5324115,0,116,0,69,
@@ -4565,265 +5326,204 @@ public yyLSLSyntax
4565114,0,101,0,115, 5326114,0,101,0,115,
45660,115,0,105,0, 53270,115,0,105,0,
4567111,0,110,0,95, 5328111,0,110,0,95,
45680,57,0,1,276, 53290,52,0,1,326,
45691,3,1,7,1,
45706,1257,22,1,136,
45711,1013,1258,17,1259,
457215,1104,1,-1,1,
45735,1260,20,1261,4,
457446,80,0,97,0,
4575114,0,101,0,110,
45760,116,0,104,0,
4577101,0,115,0,105,
45780,115,0,69,0,
4579120,0,112,0,114,
45800,101,0,115,0,
4581115,0,105,0,111,
45820,110,0,95,0,
458349,0,1,266,1,
45843,1,4,1,3,
45851262,22,1,126,1,
45861332,1263,17,1264,15,
45871098,1,-1,1,5,
45881265,20,1266,4,38,
458983,0,105,0,109,
45900,112,0,108,0,
4591101,0,65,0,115,
45920,115,0,105,0,
4593103,0,110,0,109,
45940,101,0,110,0,
4595116,0,95,0,49,
45960,57,0,1,218,
45971,3,1,6,1, 53301,3,1,6,1,
45985,1267,22,1,78, 53315,1375,22,1,162,
45991,2337,1268,17,1142, 53321,74,1376,17,1377,
46001,0,1146,1,1585, 533315,1347,1,-1,1,
46011269,17,1270,15,1271, 53345,1378,20,1379,4,
46024,32,37,0,82, 533540,84,0,121,0,
46030,101,0,116,0, 5336112,0,101,0,99,
4604117,0,114,0,110, 53370,97,0,115,0,
46050,83,0,116,0, 5338116,0,69,0,120,
460697,0,116,0,101,
46070,109,0,101,0,
4608110,0,116,0,1,
4609-1,1,5,1272,20,
46101273,4,34,82,0,
4611101,0,116,0,117,
46120,114,0,110,0,
461383,0,116,0,97,
46140,116,0,101,0,
4615109,0,101,0,110,
46160,116,0,95,0,
461750,0,1,225,1,
46183,1,2,1,1,
46191274,22,1,85,1,
46202023,1275,17,1276,15,
46211137,1,-1,1,5,
46221277,20,1278,4,26,
462383,0,116,0,97,
46240,116,0,101,0,
462567,0,104,0,97,
46260,110,0,103,0,
4627101,0,95,0,50,
46280,1,183,1,3,
46291,3,1,2,1279,
463022,1,43,1,2136,
4631842,1,82,1280,17,
46321281,15,1282,4,32,
463337,0,85,0,110,
46340,97,0,114,0,
4635121,0,69,0,120,
46360,112,0,114,0, 53390,112,0,114,0,
4637101,0,115,0,115, 5340101,0,115,0,115,
46380,105,0,111,0, 53410,105,0,111,0,
4639110,0,1,-1,1, 5342110,0,95,0,57,
46405,1283,20,1284,4, 53430,1,331,1,3,
464134,85,0,110,0, 53441,7,1,6,1380,
464297,0,114,0,121, 534522,1,167,1,1013,
53461381,17,1382,15,1226,
53471,-1,1,5,1383,
534820,1384,4,46,80,
53490,97,0,114,0,
5350101,0,110,0,116,
53510,104,0,101,0,
5352115,0,105,0,115,
46430,69,0,120,0, 53530,69,0,120,0,
4644112,0,114,0,101, 5354112,0,114,0,101,
46450,115,0,115,0, 53550,115,0,115,0,
4646105,0,111,0,110, 5356105,0,111,0,110,
46470,95,0,51,0,
46481,265,1,3,1,
46493,1,2,1285,22,
46501,125,1,2026,1286,
465117,1287,15,1288,4,
465228,37,0,74,0,
4653117,0,109,0,112,
46540,83,0,116,0,
465597,0,116,0,101,
46560,109,0,101,0,
4657110,0,116,0,1,
4658-1,1,5,1289,20,
46591290,4,30,74,0,
4660117,0,109,0,112,
46610,83,0,116,0,
466297,0,116,0,101,
46630,109,0,101,0,
4664110,0,116,0,95,
46650,49,0,1,181,
46661,3,1,3,1,
46672,1291,22,1,41,
46681,1591,1292,17,1293,
466915,1271,1,-1,1,
46705,1294,20,1295,4,
467134,82,0,101,0,
4672116,0,117,0,114,
46730,110,0,83,0,
4674116,0,97,0,116,
46750,101,0,109,0,
4676101,0,110,0,116,
46770,95,0,49,0, 53570,95,0,49,0,
46781,224,1,3,1, 53581,321,1,3,1,
46793,1,2,1296,22, 53594,1,3,1385,22,
46801,84,1,1341,1297, 53601,157,1,1332,1386,
468117,1298,15,1098,1, 536117,1387,15,1220,1,
4682-1,1,5,1299,20, 5362-1,1,5,1388,20,
46831300,4,36,83,0, 53631389,4,38,83,0,
4684105,0,109,0,112, 5364105,0,109,0,112,
46850,108,0,101,0, 53650,108,0,101,0,
468665,0,115,0,115, 536665,0,115,0,115,
46870,105,0,103,0, 53670,105,0,103,0,
4688110,0,109,0,101, 5368110,0,109,0,101,
46890,110,0,116,0, 53690,110,0,116,0,
469095,0,54,0,1, 537095,0,49,0,57,
4691205,1,3,1,4, 53710,1,273,1,3,
46921,3,1301,22,1, 53721,6,1,5,1390,
469365,1,2030,731,1, 537322,1,109,1,2337,
4694328,1302,17,1303,15, 53741391,17,1264,1,0,
46951121,1,-1,1,5, 53751268,1,1585,1392,17,
46961304,20,1305,4,36, 53761393,15,1394,4,32,
469766,0,105,0,110, 537737,0,82,0,101,
46980,97,0,114,0, 53780,116,0,117,0,
4699121,0,69,0,120, 5379114,0,110,0,83,
47000,112,0,114,0, 53800,116,0,97,0,
4701101,0,115,0,115, 5381116,0,101,0,109,
47020,105,0,111,0, 53820,101,0,110,0,
4703110,0,95,0,50, 5383116,0,1,-1,1,
47040,1,246,1,3, 53845,1395,20,1396,4,
47051,4,1,3,1306, 538534,82,0,101,0,
470622,1,106,1,1303, 5386116,0,117,0,114,
47071307,17,1308,15,1098, 53870,110,0,83,0,
47081,-1,1,5,1309, 5388116,0,97,0,116,
470920,1310,4,36,83, 53890,101,0,109,0,
47100,105,0,109,0,
4711112,0,108,0,101,
47120,65,0,115,0,
4713115,0,105,0,103,
47140,110,0,109,0,
4715101,0,110,0,116,
47160,95,0,55,0,
47171,206,1,3,1,
47186,1,5,1311,22,
47191,66,1,1096,1312,
472017,1313,15,1314,4,
472126,37,0,70,0,
4722117,0,110,0,99,
47230,116,0,105,0,
4724111,0,110,0,67,
47250,97,0,108,0,
4726108,0,1,-1,1,
47275,1315,20,1316,4,
472828,70,0,117,0,
4729110,0,99,0,116,
47300,105,0,111,0,
4731110,0,67,0,97,
47320,108,0,108,0,
473395,0,49,0,1,
4734277,1,3,1,5,
47351,4,1317,22,1,
4736137,1,93,1318,17,
47371319,15,1282,1,-1,
47381,5,1320,20,1321,
47394,34,85,0,110,
47400,97,0,114,0,
4741121,0,69,0,120,
47420,112,0,114,0,
4743101,0,115,0,115,
47440,105,0,111,0,
4745110,0,95,0,50,
47460,1,264,1,3,
47471,3,1,2,1322,
474822,1,124,1,1550,
47491323,17,1324,15,1098,
47501,-1,1,5,1325,
475120,1326,4,38,83,
47520,105,0,109,0,
4753112,0,108,0,101,
47540,65,0,115,0,
4755115,0,105,0,103,
47560,110,0,109,0,
4757101,0,110,0,116, 5390101,0,110,0,116,
47580,95,0,49,0, 53910,95,0,50,0,
475951,0,1,212,1, 53921,280,1,3,1,
53932,1,1,1397,22,
53941,116,1,2023,1398,
539517,1399,15,1259,1,
5396-1,1,5,1400,20,
53971401,4,26,83,0,
5398116,0,97,0,116,
53990,101,0,67,0,
5400104,0,97,0,110,
54010,103,0,101,0,
540295,0,50,0,1,
5403238,1,3,1,3,
54041,2,1402,22,1,
540574,1,2136,965,1,
540682,1403,17,1404,15,
54071405,4,32,37,0,
540885,0,110,0,97,
54090,114,0,121,0,
541069,0,120,0,112,
54110,114,0,101,0,
5412115,0,115,0,105,
54130,111,0,110,0,
54141,-1,1,5,1406,
541520,1407,4,34,85,
54160,110,0,97,0,
5417114,0,121,0,69,
54180,120,0,112,0,
5419114,0,101,0,115,
54200,115,0,105,0,
5421111,0,110,0,95,
54220,51,0,1,320,
54231,3,1,3,1,
54242,1408,22,1,156,
54251,2026,1409,17,1410,
542615,1411,4,28,37,
54270,74,0,117,0,
5428109,0,112,0,83,
54290,116,0,97,0,
5430116,0,101,0,109,
54310,101,0,110,0,
5432116,0,1,-1,1,
54335,1412,20,1413,4,
543430,74,0,117,0,
5435109,0,112,0,83,
54360,116,0,97,0,
5437116,0,101,0,109,
54380,101,0,110,0,
5439116,0,95,0,49,
54400,1,236,1,3,
54411,3,1,2,1414,
544222,1,72,1,1591,
54431415,17,1416,15,1394,
54441,-1,1,5,1417,
544520,1418,4,34,82,
54460,101,0,116,0,
5447117,0,114,0,110,
54480,83,0,116,0,
544997,0,116,0,101,
54500,109,0,101,0,
5451110,0,116,0,95,
54520,49,0,1,279,
54531,3,1,3,1,
54542,1419,22,1,115,
54551,1341,1420,17,1421,
545615,1220,1,-1,1,
54575,1422,20,1423,4,
545836,83,0,105,0,
5459109,0,112,0,108,
54600,101,0,65,0,
5461115,0,115,0,105,
54620,103,0,110,0,
5463109,0,101,0,110,
54640,116,0,95,0,
546554,0,1,260,1,
47603,1,4,1,3, 54663,1,4,1,3,
47611327,22,1,72,1, 54671424,22,1,96,1,
47622040,1328,16,0,532, 54682030,853,1,328,1425,
47631,2106,1329,17,1142, 546917,1426,15,1243,1,
47641,0,1146,1,1555, 5470-1,1,5,1427,20,
47651330,16,0,599,1, 54711428,4,36,66,0,
4766827,1331,17,1332,15,
47671121,1,-1,1,5,
47681333,20,1334,4,38,
476966,0,105,0,110,
47700,97,0,114,0,
4771121,0,69,0,120,
47720,112,0,114,0,
4773101,0,115,0,115,
47740,105,0,111,0,
4775110,0,95,0,49,
47760,53,0,1,259,
47771,3,1,4,1,
47783,1335,22,1,119,
47791,1859,1336,16,0,
4780304,1,1860,821,1,
47811804,1337,17,1142,1,
47820,1146,1,107,1338,
478317,1339,15,1282,1,
4784-1,1,5,1340,20,
47851341,4,34,85,0,
4786110,0,97,0,114,
47870,121,0,69,0,
4788120,0,112,0,114,
47890,101,0,115,0,
4790115,0,105,0,111,
47910,110,0,95,0,
479249,0,1,263,1,
47933,1,3,1,2,
47941342,22,1,123,1,
47951114,1343,17,1185,1,
47963,1189,1,1048,1344,
479717,1345,15,1121,1,
4798-1,1,5,1346,20,
47991347,4,38,66,0,
4800105,0,110,0,97, 5472105,0,110,0,97,
48010,114,0,121,0, 54730,114,0,121,0,
480269,0,120,0,112, 547469,0,120,0,112,
48030,114,0,101,0, 54750,114,0,101,0,
4804115,0,115,0,105, 5476115,0,115,0,105,
48050,111,0,110,0, 54770,111,0,110,0,
480695,0,49,0,56, 547895,0,50,0,1,
48070,1,262,1,3, 5479301,1,3,1,4,
48081,4,1,3,1348, 54801,3,1429,22,1,
480922,1,122,1,352, 5481137,1,1303,1430,17,
48101349,17,1350,15,1121, 54821431,15,1220,1,-1,
48111,-1,1,5,1351, 54831,5,1432,20,1433,
481220,1352,4,36,66, 54844,36,83,0,105,
48130,105,0,110,0, 54850,109,0,112,0,
481497,0,114,0,121, 5486108,0,101,0,65,
48150,69,0,120,0,
4816112,0,114,0,101,
48170,115,0,115,0, 54870,115,0,115,0,
4818105,0,111,0,110, 5488105,0,103,0,110,
48190,95,0,49,0, 54890,109,0,101,0,
48201,245,1,3,1, 5490110,0,116,0,95,
48214,1,3,1353,22, 54910,55,0,1,261,
48221,105,1,1872,1354, 54921,3,1,6,1,
482316,0,314,1,1873, 54935,1434,22,1,97,
4824835,1,118,1355,17, 54941,2035,874,1,93,
48251356,15,1121,1,-1, 54951435,17,1436,15,1405,
48261,5,1357,20,1358, 54961,-1,1,5,1437,
549720,1438,4,34,85,
54980,110,0,97,0,
5499114,0,121,0,69,
55000,120,0,112,0,
5501114,0,101,0,115,
55020,115,0,105,0,
5503111,0,110,0,95,
55040,50,0,1,319,
55051,3,1,3,1,
55062,1439,22,1,155,
55071,1550,1440,17,1441,
550815,1220,1,-1,1,
55095,1442,20,1443,4,
551038,83,0,105,0,
5511109,0,112,0,108,
55120,101,0,65,0,
5513115,0,115,0,105,
55140,103,0,110,0,
5515109,0,101,0,110,
55160,116,0,95,0,
551749,0,51,0,1,
5518267,1,3,1,4,
55191,3,1444,22,1,
5520103,1,2040,1445,16,
55210,610,1,2106,1446,
552217,1264,1,0,1268,
55231,1555,1447,16,0,
5524707,1,827,1448,17,
55251449,15,1243,1,-1,
55261,5,1450,20,1451,
48274,38,66,0,105, 55274,38,66,0,105,
48280,110,0,97,0, 55280,110,0,97,0,
4829114,0,121,0,69, 5529114,0,121,0,69,
@@ -4831,36 +5531,85 @@ public yyLSLSyntax
4831114,0,101,0,115, 5531114,0,101,0,115,
48320,115,0,105,0, 55320,115,0,105,0,
4833111,0,110,0,95, 5533111,0,110,0,95,
48340,49,0,52,0, 55340,49,0,53,0,
48351,258,1,3,1, 55351,314,1,3,1,
48364,1,3,1359,22, 55364,1,3,1452,22,
48371,118,1,1123,1360, 55371,150,1,1859,1453,
483817,1361,15,1098,1, 553816,0,339,1,1860,
4839-1,1,5,1362,20, 5539943,1,1804,1454,17,
48401363,4,38,83,0, 55401264,1,0,1268,1,
4841105,0,109,0,112, 5541107,1455,17,1456,15,
48420,108,0,101,0, 55421405,1,-1,1,5,
484365,0,115,0,115, 55431457,20,1458,4,34,
48440,105,0,103,0, 554485,0,110,0,97,
4845110,0,109,0,101, 55450,114,0,121,0,
48460,110,0,116,0, 554669,0,120,0,112,
484795,0,49,0,50, 55470,114,0,101,0,
48480,1,211,1,3, 5548115,0,115,0,105,
48491,6,1,5,1364,
485022,1,71,1,371,
48511365,17,1366,15,1367,
48524,46,37,0,70,
48530,117,0,110,0,
485499,0,116,0,105,
48550,111,0,110,0, 55490,111,0,110,0,
485667,0,97,0,108, 555095,0,49,0,1,
48570,108,0,69,0, 5551318,1,3,1,3,
55521,2,1459,22,1,
5553154,1,2781,1460,16,
55540,278,1,1114,1461,
555517,1308,1,3,1312,
55561,1048,1462,17,1463,
555715,1243,1,-1,1,
55585,1464,20,1465,4,
555938,66,0,105,0,
5560110,0,97,0,114,
55610,121,0,69,0,
4858120,0,112,0,114, 5562120,0,112,0,114,
48590,101,0,115,0, 55630,101,0,115,0,
4860115,0,105,0,111, 5564115,0,105,0,111,
48610,110,0,1,-1, 55650,110,0,95,0,
48621,5,1368,20,1369, 556649,0,56,0,1,
48634,48,70,0,117, 5567317,1,3,1,4,
55681,3,1466,22,1,
5569153,1,352,1467,17,
55701468,15,1243,1,-1,
55711,5,1469,20,1470,
55724,36,66,0,105,
55730,110,0,97,0,
5574114,0,121,0,69,
55750,120,0,112,0,
5576114,0,101,0,115,
55770,115,0,105,0,
5578111,0,110,0,95,
55790,49,0,1,300,
55801,3,1,4,1,
55813,1471,22,1,136,
55821,1872,1472,16,0,
5583349,1,1873,958,1,
5584118,1473,17,1474,15,
55851243,1,-1,1,5,
55861475,20,1476,4,38,
558766,0,105,0,110,
55880,97,0,114,0,
5589121,0,69,0,120,
55900,112,0,114,0,
5591101,0,115,0,115,
55920,105,0,111,0,
5593110,0,95,0,49,
55940,52,0,1,313,
55951,3,1,4,1,
55963,1477,22,1,149,
55971,1123,1478,17,1479,
559815,1220,1,-1,1,
55995,1480,20,1481,4,
560038,83,0,105,0,
5601109,0,112,0,108,
56020,101,0,65,0,
5603115,0,115,0,105,
56040,103,0,110,0,
5605109,0,101,0,110,
56060,116,0,95,0,
560749,0,50,0,1,
5608266,1,3,1,6,
56091,5,1482,22,1,
5610102,1,371,1483,17,
56111484,15,1485,4,46,
561237,0,70,0,117,
48640,110,0,99,0, 56130,110,0,99,0,
4865116,0,105,0,111, 5614116,0,105,0,111,
48660,110,0,67,0, 56150,110,0,67,0,
@@ -4869,43 +5618,36 @@ public yyLSLSyntax
4869112,0,114,0,101, 5618112,0,114,0,101,
48700,115,0,115,0, 56190,115,0,115,0,
4871105,0,111,0,110, 5620105,0,111,0,110,
48720,95,0,49,0, 56210,1,-1,1,5,
48731,244,1,3,1, 56221486,20,1487,4,48,
48742,1,1,1370,22, 562370,0,117,0,110,
48751,104,1,1377,1371, 56240,99,0,116,0,
487617,1372,15,1098,1, 5625105,0,111,0,110,
4877-1,1,5,1373,20, 56260,67,0,97,0,
48781374,4,36,83,0, 5627108,0,108,0,69,
4879105,0,109,0,112, 56280,120,0,112,0,
48800,108,0,101,0, 5629114,0,101,0,115,
488165,0,115,0,115, 56300,115,0,105,0,
48820,105,0,103,0, 5631111,0,110,0,95,
4883110,0,109,0,101, 56320,49,0,1,299,
48840,110,0,116,0, 56331,3,1,2,1,
488595,0,53,0,1, 56341,1488,22,1,135,
4886204,1,3,1,4, 56351,1377,1489,17,1490,
48871,3,1375,22,1, 563615,1220,1,-1,1,
488864,1,375,1376,17, 56375,1491,20,1492,4,
48891377,15,1192,1,-1, 563836,83,0,105,0,
48901,5,1378,20,1379, 5639109,0,112,0,108,
48914,60,73,0,110, 56400,101,0,65,0,
48920,99,0,114,0, 5641115,0,115,0,105,
4893101,0,109,0,101, 56420,103,0,110,0,
48940,110,0,116,0,
489568,0,101,0,99,
48960,114,0,101,0,
4897109,0,101,0,110, 5643109,0,101,0,110,
48980,116,0,69,0, 56440,116,0,95,0,
4899120,0,112,0,114, 564553,0,1,259,1,
49000,101,0,115,0, 56463,1,4,1,3,
4901115,0,105,0,111, 56471493,22,1,95,1,
49020,110,0,95,0, 5648375,1494,17,1495,15,
490356,0,1,243,1, 56491315,1,-1,1,5,
49043,1,5,1,4, 56501496,20,1497,4,60,
49051380,22,1,103,1,
4906377,1381,17,1382,15,
49071192,1,-1,1,5,
49081383,20,1384,4,60,
490973,0,110,0,99, 565173,0,110,0,99,
49100,114,0,101,0, 56520,114,0,101,0,
4911109,0,101,0,110, 5653109,0,101,0,110,
@@ -4917,13 +5659,13 @@ public yyLSLSyntax
4917112,0,114,0,101, 5659112,0,114,0,101,
49180,115,0,115,0, 56600,115,0,115,0,
4919105,0,111,0,110, 5661105,0,111,0,110,
49200,95,0,53,0, 56620,95,0,56,0,
49211,240,1,3,1, 56631,298,1,3,1,
49223,1,2,1385,22, 56645,1,4,1498,22,
49231,100,1,379,1386, 56651,134,1,377,1499,
492417,1387,15,1192,1, 566617,1500,15,1315,1,
4925-1,1,5,1388,20, 5667-1,1,5,1501,20,
49261389,4,60,73,0, 56681502,4,60,73,0,
4927110,0,99,0,114, 5669110,0,99,0,114,
49280,101,0,109,0, 56700,101,0,109,0,
4929101,0,110,0,116, 5671101,0,110,0,116,
@@ -4935,81 +5677,51 @@ public yyLSLSyntax
4935114,0,101,0,115, 5677114,0,101,0,115,
49360,115,0,105,0, 56780,115,0,105,0,
4937111,0,110,0,95, 5679111,0,110,0,95,
49380,55,0,1,242, 56800,53,0,1,295,
49391,3,1,5,1, 56811,3,1,3,1,
49404,1390,22,1,102, 56822,1503,22,1,131,
49411,380,1391,17,1392, 56831,379,1504,17,1505,
494215,1393,4,38,37, 568415,1315,1,-1,1,
49430,67,0,111,0, 56855,1506,20,1507,4,
4944110,0,115,0,116, 568660,73,0,110,0,
49450,97,0,110,0, 568799,0,114,0,101,
4946116,0,69,0,120, 56880,109,0,101,0,
49470,112,0,114,0, 5689110,0,116,0,68,
4948101,0,115,0,115, 56900,101,0,99,0,
49490,105,0,111,0, 5691114,0,101,0,109,
4950110,0,1,-1,1, 56920,101,0,110,0,
49515,1394,20,1395,4,
495240,67,0,111,0,
4953110,0,115,0,116,
49540,97,0,110,0,
4955116,0,69,0,120, 5693116,0,69,0,120,
49560,112,0,114,0, 56940,112,0,114,0,
4957101,0,115,0,115, 5695101,0,115,0,115,
49580,105,0,111,0, 56960,105,0,111,0,
4959110,0,95,0,49, 5697110,0,95,0,55,
49600,1,233,1,3, 56980,1,297,1,3,
49611,2,1,1,1396, 56991,5,1,4,1508,
496222,1,93,1,883, 570022,1,133,1,380,
49631397,17,1398,15,1121, 57011509,17,1510,15,1511,
49641,-1,1,5,1399, 57024,38,37,0,67,
496520,1400,4,38,66, 57030,111,0,110,0,
49660,105,0,110,0, 5704115,0,116,0,97,
496797,0,114,0,121,
49680,69,0,120,0,
4969112,0,114,0,101,
49700,115,0,115,0,
4971105,0,111,0,110,
49720,95,0,49,0,
497354,0,1,260,1,
49743,1,4,1,3,
49751401,22,1,120,1,
49761628,1402,17,1403,15,
49771404,4,22,37,0,
497865,0,115,0,115,
49790,105,0,103,0,
4980110,0,109,0,101,
49810,110,0,116,0, 57050,110,0,116,0,
49821,-1,1,5,1405, 570669,0,120,0,112,
498320,1406,4,24,65, 57070,114,0,101,0,
49840,115,0,115,0, 5708115,0,115,0,105,
4985105,0,103,0,110, 57090,111,0,110,0,
49860,109,0,101,0, 57101,-1,1,5,1512,
4987110,0,116,0,95, 571120,1513,4,40,67,
49880,49,0,1,198, 57120,111,0,110,0,
49891,3,1,4,1, 5713115,0,116,0,97,
49903,1407,22,1,58,
49911,2075,1408,17,1142,
49921,0,1146,1,373,
49931409,17,1410,15,1192,
49941,-1,1,5,1411,
499520,1412,4,60,73,
49960,110,0,99,0,
4997114,0,101,0,109,
49980,101,0,110,0,
4999116,0,68,0,101,
50000,99,0,114,0,
5001101,0,109,0,101,
50020,110,0,116,0, 57140,110,0,116,0,
500369,0,120,0,112, 571569,0,120,0,112,
50040,114,0,101,0, 57160,114,0,101,0,
5005115,0,115,0,105, 5717115,0,115,0,105,
50060,111,0,110,0, 57180,111,0,110,0,
500795,0,54,0,1, 571995,0,49,0,1,
5008241,1,3,1,3, 5720288,1,3,1,2,
50091,2,1413,22,1, 57211,1,1514,22,1,
5010101,1,130,1414,17, 5722124,1,883,1515,17,
50111415,15,1121,1,-1, 57231516,15,1243,1,-1,
50121,5,1416,20,1417, 57241,5,1517,20,1518,
50134,38,66,0,105, 57254,38,66,0,105,
50140,110,0,97,0, 57260,110,0,97,0,
5015114,0,121,0,69, 5727114,0,121,0,69,
@@ -5017,71 +5729,47 @@ public yyLSLSyntax
5017114,0,101,0,115, 5729114,0,101,0,115,
50180,115,0,105,0, 57300,115,0,105,0,
5019111,0,110,0,95, 5731111,0,110,0,95,
50200,49,0,51,0, 57320,49,0,54,0,
50211,257,1,3,1, 57331,315,1,3,1,
50224,1,3,1418,22, 57344,1,3,1519,22,
50231,117,1,143,1419, 57351,151,1,1628,1520,
502417,1420,15,1121,1, 573617,1521,15,1522,4,
5025-1,1,5,1421,20, 573722,37,0,65,0,
50261422,4,38,66,0,
5027105,0,110,0,97,
50280,114,0,121,0,
502969,0,120,0,112,
50300,114,0,101,0,
5031115,0,115,0,105, 5738115,0,115,0,105,
50320,111,0,110,0, 57390,103,0,110,0,
503395,0,49,0,50, 5740109,0,101,0,110,
50340,1,256,1,3, 57410,116,0,1,-1,
50351,4,1,3,1423, 57421,5,1523,20,1524,
503622,1,116,1,1901, 57434,24,65,0,115,
50371424,17,1142,1,0, 57440,115,0,105,0,
50381146,1,2657,1425,16, 5745103,0,110,0,109,
50390,608,1,1152,1426, 57460,101,0,110,0,
504017,1427,15,1098,1, 5747116,0,95,0,49,
5041-1,1,5,1428,20, 57480,1,253,1,3,
50421429,4,38,83,0, 57491,4,1,3,1525,
5043105,0,109,0,112, 575022,1,89,1,2075,
50440,108,0,101,0, 57511526,17,1264,1,0,
504565,0,115,0,115, 57521268,1,373,1527,17,
50460,105,0,103,0, 57531528,15,1315,1,-1,
5047110,0,109,0,101, 57541,5,1529,20,1530,
57554,60,73,0,110,
57560,99,0,114,0,
5757101,0,109,0,101,
50480,110,0,116,0, 57580,110,0,116,0,
504995,0,50,0,52, 575968,0,101,0,99,
50500,1,223,1,3, 57600,114,0,101,0,
50511,6,1,5,1430, 5761109,0,101,0,110,
505222,1,83,1,1406, 57620,116,0,69,0,
50531431,17,1432,15,1098, 5763120,0,112,0,114,
50541,-1,1,5,1433, 57640,101,0,115,0,
505520,1434,4,38,83, 5765115,0,105,0,111,
50560,105,0,109,0, 57660,110,0,95,0,
5057112,0,108,0,101, 576754,0,1,296,1,
50580,65,0,115,0, 57683,1,3,1,2,
5059115,0,105,0,103, 57691531,22,1,132,1,
50600,110,0,109,0, 5770130,1532,17,1533,15,
5061101,0,110,0,116, 57711243,1,-1,1,5,
50620,95,0,49,0, 57721534,20,1535,4,38,
506355,0,1,216,1,
50643,1,4,1,3,
50651435,22,1,76,1,
50661659,1436,16,0,269,
50671,2413,1437,17,1142,
50681,0,1146,1,1159,
50691438,17,1439,15,1098,
50701,-1,1,5,1440,
507120,1441,4,38,83,
50720,105,0,109,0,
5073112,0,108,0,101,
50740,65,0,115,0,
5075115,0,105,0,103,
50760,110,0,109,0,
5077101,0,110,0,116,
50780,95,0,49,0,
507949,0,1,210,1,
50803,1,6,1,5,
50811442,22,1,70,1,
5082157,1443,17,1444,15,
50831121,1,-1,1,5,
50841445,20,1446,4,38,
508566,0,105,0,110, 577366,0,105,0,110,
50860,97,0,114,0, 57740,97,0,114,0,
5087121,0,69,0,120, 5775121,0,69,0,120,
@@ -5089,38 +5777,40 @@ public yyLSLSyntax
5089101,0,115,0,115, 5777101,0,115,0,115,
50900,105,0,111,0, 57780,105,0,111,0,
5091110,0,95,0,49, 5779110,0,95,0,49,
50920,49,0,1,255, 57800,51,0,1,312,
50931,3,1,4,1, 57811,3,1,4,1,
50943,1447,22,1,115, 57823,1536,22,1,148,
50951,1413,1448,17,1449, 57831,143,1537,17,1538,
509615,1098,1,-1,1, 578415,1243,1,-1,1,
50975,1450,20,1451,4, 57855,1539,20,1540,4,
509836,83,0,105,0, 578638,66,0,105,0,
5099109,0,112,0,108, 5787110,0,97,0,114,
51000,101,0,65,0, 57880,121,0,69,0,
5101115,0,115,0,105, 5789120,0,112,0,114,
51020,103,0,110,0, 57900,101,0,115,0,
5103109,0,101,0,110, 5791115,0,105,0,111,
51040,116,0,95,0, 57920,110,0,95,0,
510552,0,1,203,1, 579349,0,50,0,1,
51063,1,4,1,3, 5794311,1,3,1,4,
51071452,22,1,63,1, 57951,3,1541,22,1,
51081370,1453,17,1454,15, 5796147,1,1901,1542,17,
51091098,1,-1,1,5, 57971264,1,0,1268,1,
51101455,20,1456,4,38, 57981152,1543,17,1544,15,
57991220,1,-1,1,5,
58001545,20,1546,4,38,
511183,0,105,0,109, 580183,0,105,0,109,
51120,112,0,108,0, 58020,112,0,108,0,
5113101,0,65,0,115, 5803101,0,65,0,115,
51140,115,0,105,0, 58040,115,0,105,0,
5115103,0,110,0,109, 5805103,0,110,0,109,
51160,101,0,110,0, 58060,101,0,110,0,
5117116,0,95,0,49, 5807116,0,95,0,50,
51180,56,0,1,217, 58080,52,0,1,278,
51191,3,1,4,1, 58091,3,1,6,1,
51203,1457,22,1,77, 58105,1547,22,1,114,
51211,1478,1458,17,1459, 58111,1406,1548,17,1549,
512215,1098,1,-1,1, 581215,1220,1,-1,1,
51235,1460,20,1461,4, 58135,1550,20,1551,4,
512438,83,0,105,0, 581438,83,0,105,0,
5125109,0,112,0,108, 5815109,0,112,0,108,
51260,101,0,65,0, 58160,101,0,65,0,
@@ -5128,52 +5818,54 @@ public yyLSLSyntax
51280,103,0,110,0, 58180,103,0,110,0,
5129109,0,101,0,110, 5819109,0,101,0,110,
51300,116,0,95,0, 58200,116,0,95,0,
513149,0,53,0,1, 582149,0,55,0,1,
5132214,1,3,1,4, 5822271,1,3,1,4,
51331,3,1462,22,1, 58231,3,1552,22,1,
513474,1,1620,1463,17, 5824107,1,1659,1553,16,
51351464,15,1404,1,-1, 58250,297,1,2413,1554,
51361,5,1465,20,1466, 582617,1264,1,0,1268,
51374,24,65,0,115, 58271,1159,1555,17,1556,
51380,115,0,105,0, 582815,1220,1,-1,1,
5139103,0,110,0,109, 58295,1557,20,1558,4,
51400,101,0,110,0, 583038,83,0,105,0,
5141116,0,95,0,50, 5831109,0,112,0,108,
51420,1,199,1,3, 58320,101,0,65,0,
51431,2,1,1,1467,
514422,1,59,1,1621,
51451468,16,0,668,1,
51461574,799,1,172,1469,
514717,1470,15,1121,1,
5148-1,1,5,1471,20,
51491472,4,38,66,0,
5150105,0,110,0,97,
51510,114,0,121,0,
515269,0,120,0,112,
51530,114,0,101,0,
5154115,0,115,0,105, 5833115,0,115,0,105,
51550,111,0,110,0, 58340,103,0,110,0,
515695,0,49,0,48, 5835109,0,101,0,110,
51570,1,254,1,3, 58360,116,0,95,0,
51581,4,1,3,1473, 583749,0,49,0,1,
515922,1,114,1,1931, 5838265,1,3,1,6,
5160861,1,1665,1474,17, 58391,5,1559,22,1,
51611475,15,1156,1,-1, 5840101,1,157,1560,17,
51621,5,1476,20,1477, 58411561,15,1243,1,-1,
51634,36,70,0,111, 58421,5,1562,20,1563,
51640,114,0,76,0, 58434,38,66,0,105,
5165111,0,111,0,112, 58440,110,0,97,0,
51660,83,0,116,0, 5845114,0,121,0,69,
516797,0,116,0,101, 58460,120,0,112,0,
51680,109,0,101,0, 5847114,0,101,0,115,
5169110,0,116,0,95, 58480,115,0,105,0,
51700,49,0,1,194, 5849111,0,110,0,95,
51711,3,1,2,1, 58500,49,0,49,0,
51721,1478,22,1,54, 58511,310,1,3,1,
51731,2364,827,1,2105, 58524,1,3,1564,22,
5174814,1,1188,1479,17, 58531,146,1,1413,1565,
51751480,15,1098,1,-1, 585417,1566,15,1220,1,
51761,5,1481,20,1482, 5855-1,1,5,1567,20,
58561568,4,36,83,0,
5857105,0,109,0,112,
58580,108,0,101,0,
585965,0,115,0,115,
58600,105,0,103,0,
5861110,0,109,0,101,
58620,110,0,116,0,
586395,0,52,0,1,
5864258,1,3,1,4,
58651,3,1569,22,1,
586694,1,1370,1570,17,
58671571,15,1220,1,-1,
58681,5,1572,20,1573,
51774,38,83,0,105, 58694,38,83,0,105,
51780,109,0,112,0, 58700,109,0,112,0,
5179108,0,101,0,65, 5871108,0,101,0,65,
@@ -5181,27 +5873,38 @@ public yyLSLSyntax
5181105,0,103,0,110, 5873105,0,103,0,110,
51820,109,0,101,0, 58740,109,0,101,0,
5183110,0,116,0,95, 5875110,0,116,0,95,
51840,50,0,51,0, 58760,49,0,56,0,
51851,222,1,3,1, 58771,272,1,3,1,
51866,1,5,1483,22, 58784,1,3,1574,22,
51871,82,1,1442,1484, 58791,108,1,1478,1575,
518817,1485,15,1098,1, 588017,1576,15,1220,1,
5189-1,1,5,1486,20, 5881-1,1,5,1577,20,
51901487,4,38,83,0, 58821578,4,38,83,0,
5191105,0,109,0,112, 5883105,0,109,0,112,
51920,108,0,101,0, 58840,108,0,101,0,
519365,0,115,0,115, 588565,0,115,0,115,
51940,105,0,103,0, 58860,105,0,103,0,
5195110,0,109,0,101, 5887110,0,109,0,101,
51960,110,0,116,0, 58880,110,0,116,0,
519795,0,49,0,54, 588995,0,49,0,53,
51980,1,215,1,3, 58900,1,269,1,3,
51991,4,1,3,1488, 58911,4,1,3,1579,
520022,1,75,1,1694, 589222,1,105,1,1620,
52011489,16,0,190,1, 58931580,17,1581,15,1522,
5202942,1490,17,1491,15, 58941,-1,1,5,1582,
52031121,1,-1,1,5, 589520,1583,4,24,65,
52041492,20,1493,4,38, 58960,115,0,115,0,
5897105,0,103,0,110,
58980,109,0,101,0,
5899110,0,116,0,95,
59000,50,0,1,254,
59011,3,1,2,1,
59021,1584,22,1,90,
59031,1621,1585,16,0,
5904786,1,1574,921,1,
5905172,1586,17,1587,15,
59061243,1,-1,1,5,
59071588,20,1589,4,38,
520566,0,105,0,110, 590866,0,105,0,110,
52060,97,0,114,0, 59090,97,0,114,0,
5207121,0,69,0,120, 5910121,0,69,0,120,
@@ -5209,88 +5912,170 @@ public yyLSLSyntax
5209101,0,115,0,115, 5912101,0,115,0,115,
52100,105,0,111,0, 59130,105,0,111,0,
5211110,0,95,0,49, 5914110,0,95,0,49,
52120,55,0,1,261, 59150,48,0,1,309,
52131,3,1,4,1, 59161,3,1,4,1,
52143,1494,22,1,121, 59173,1590,22,1,145,
52151,2198,1495,17,1142, 59181,1931,983,1,1665,
52161,0,1146,1,1195, 59191591,17,1592,15,1278,
52171496,17,1497,15,1098, 59201,-1,1,5,1593,
52181,-1,1,5,1498, 592120,1594,4,36,70,
521920,1499,4,38,83, 59220,111,0,114,0,
592376,0,111,0,111,
59240,112,0,83,0,
5925116,0,97,0,116,
59260,101,0,109,0,
5927101,0,110,0,116,
59280,95,0,49,0,
59291,249,1,3,1,
59302,1,1,1595,22,
59311,85,1,2364,949,
59321,2105,936,1,1188,
59331596,17,1597,15,1220,
59341,-1,1,5,1598,
593520,1599,4,38,83,
52200,105,0,109,0, 59360,105,0,109,0,
5221112,0,108,0,101, 5937112,0,108,0,101,
52220,65,0,115,0, 59380,65,0,115,0,
5223115,0,105,0,103, 5939115,0,105,0,103,
52240,110,0,109,0, 59400,110,0,109,0,
5225101,0,110,0,116, 5941101,0,110,0,116,
52260,95,0,49,0, 59420,95,0,50,0,
522748,0,1,209,1, 594351,0,1,277,1,
52283,1,6,1,5, 59443,1,6,1,5,
52291500,22,1,69,1, 59451600,22,1,113,1,
52301449,1501,17,1502,15, 59461442,1601,17,1602,15,
52311098,1,-1,1,5, 59471220,1,-1,1,5,
52321503,20,1504,4,36, 59481603,20,1604,4,38,
523383,0,105,0,109, 594983,0,105,0,109,
52340,112,0,108,0, 59500,112,0,108,0,
5235101,0,65,0,115, 5951101,0,65,0,115,
52360,115,0,105,0, 59520,115,0,105,0,
5237103,0,110,0,109, 5953103,0,110,0,109,
52380,101,0,110,0, 59540,101,0,110,0,
5239116,0,95,0,51, 5955116,0,95,0,49,
52400,1,202,1,3, 59560,54,0,1,270,
52411,4,1,3,1505, 59571,3,1,4,1,
524222,1,62,1,1701, 59583,1605,22,1,106,
52431506,17,1507,15,1156, 59591,1694,1606,16,0,
52441,-1,1,5,1508, 5960218,1,942,1607,17,
524520,1509,4,36,70, 59611608,15,1243,1,-1,
52460,111,0,114,0, 59621,5,1609,20,1610,
524776,0,111,0,111, 59634,38,66,0,105,
52480,112,0,83,0, 59640,110,0,97,0,
5249116,0,97,0,116, 5965114,0,121,0,69,
52500,101,0,109,0, 59660,120,0,112,0,
5251101,0,110,0,116, 5967114,0,101,0,115,
52520,95,0,51,0, 59680,115,0,105,0,
52531,196,1,3,1, 5969111,0,110,0,95,
52544,1,3,1510,22, 59700,49,0,55,0,
52551,56,1,447,1511, 59711,316,1,3,1,
525617,1512,15,1513,4, 59724,1,3,1611,22,
525730,37,0,86,0, 59731,152,1,2198,1612,
5258101,0,99,0,116, 597417,1264,1,0,1268,
52590,111,0,114,0, 59751,1195,1613,17,1614,
526067,0,111,0,110, 597615,1220,1,-1,1,
52610,115,0,116,0, 59775,1615,20,1616,4,
526297,0,110,0,116, 597838,83,0,105,0,
52630,1,-1,1,5, 5979109,0,112,0,108,
52641514,20,1515,4,32, 59800,101,0,65,0,
5981115,0,115,0,105,
59820,103,0,110,0,
5983109,0,101,0,110,
59840,116,0,95,0,
598549,0,48,0,1,
5986264,1,3,1,6,
59871,5,1617,22,1,
5988100,1,1449,1618,17,
59891619,15,1220,1,-1,
59901,5,1620,20,1621,
59914,36,83,0,105,
59920,109,0,112,0,
5993108,0,101,0,65,
59940,115,0,115,0,
5995105,0,103,0,110,
59960,109,0,101,0,
5997110,0,116,0,95,
59980,51,0,1,257,
59991,3,1,4,1,
60003,1622,22,1,93,
60011,1701,1623,17,1624,
600215,1278,1,-1,1,
60035,1625,20,1626,4,
600436,70,0,111,0,
6005114,0,76,0,111,
60060,111,0,112,0,
600783,0,116,0,97,
60080,116,0,101,0,
6009109,0,101,0,110,
60100,116,0,95,0,
601151,0,1,251,1,
60123,1,4,1,3,
60131627,22,1,87,1,
6014447,1628,17,1629,15,
60151630,4,30,37,0,
526586,0,101,0,99, 601686,0,101,0,99,
52660,116,0,111,0, 60170,116,0,111,0,
5267114,0,67,0,111, 6018114,0,67,0,111,
52680,110,0,115,0, 60190,110,0,115,0,
5269116,0,97,0,110, 6020116,0,97,0,110,
52700,116,0,95,0, 60210,116,0,1,-1,
527149,0,1,231,1, 60221,5,1631,20,1632,
52723,1,8,1,7, 60234,32,86,0,101,
52731516,22,1,91,1, 60240,99,0,116,0,
52742458,876,1,2459,882, 6025111,0,114,0,67,
52751,1958,1517,17,1142, 60260,111,0,110,0,
52761,0,1146,1,188, 6027115,0,116,0,97,
52771518,17,1519,15,1121, 60280,110,0,116,0,
52781,-1,1,5,1520, 602995,0,49,0,1,
527920,1521,4,36,66, 6030286,1,3,1,8,
60311,7,1633,22,1,
6032122,1,2458,998,1,
60332459,1004,1,1958,1634,
603417,1264,1,0,1268,
60351,188,1635,17,1636,
603615,1243,1,-1,1,
60375,1637,20,1638,4,
603836,66,0,105,0,
6039110,0,97,0,114,
60400,121,0,69,0,
6041120,0,112,0,114,
60420,101,0,115,0,
6043115,0,105,0,111,
60440,110,0,95,0,
604557,0,1,308,1,
60463,1,4,1,3,
60471639,22,1,144,1,
60482462,1011,1,1657,1016,
60491,2464,1021,1,205,
60501640,17,1641,15,1243,
60511,-1,1,5,1642,
605220,1643,4,36,66,
52800,105,0,110,0, 60530,105,0,110,0,
528197,0,114,0,121, 605497,0,114,0,121,
52820,69,0,120,0, 60550,69,0,120,0,
5283112,0,114,0,101, 6056112,0,114,0,101,
52840,115,0,115,0, 60570,115,0,115,0,
5285105,0,111,0,110, 6058105,0,111,0,110,
52860,95,0,57,0, 60590,95,0,56,0,
52871,253,1,3,1, 60601,307,1,3,1,
52884,1,3,1522,22, 60614,1,3,1644,22,
52891,113,1,2462,889, 60621,143,1,2227,1030,
52901,1657,894,1,2464, 60631,1224,1645,17,1646,
5291899,1,205,1523,17, 606415,1220,1,-1,1,
52921524,15,1121,1,-1, 60655,1647,20,1648,4,
52931,5,1525,20,1526, 606638,83,0,105,0,
6067109,0,112,0,108,
60680,101,0,65,0,
6069115,0,115,0,105,
60700,103,0,110,0,
6071109,0,101,0,110,
60720,116,0,95,0,
607350,0,50,0,1,
6074276,1,3,1,6,
60751,5,1649,22,1,
6076112,1,223,1650,17,
60771651,15,1243,1,-1,
60781,5,1652,20,1653,
52944,36,66,0,105, 60794,36,66,0,105,
52950,110,0,97,0, 60800,110,0,97,0,
5296114,0,121,0,69, 6081114,0,121,0,69,
@@ -5298,131 +6083,120 @@ public yyLSLSyntax
5298114,0,101,0,115, 6083114,0,101,0,115,
52990,115,0,105,0, 60840,115,0,105,0,
5300111,0,110,0,95, 6085111,0,110,0,95,
53010,56,0,1,252, 60860,55,0,1,306,
53021,3,1,4,1, 60871,3,1,4,1,
53033,1527,22,1,112, 60883,1654,22,1,142,
53041,2227,908,1,1224, 60891,1730,1655,17,1656,
53051528,17,1529,15,1098, 609015,1278,1,-1,1,
53061,-1,1,5,1530, 60915,1657,20,1658,4,
530720,1531,4,38,83, 609236,70,0,111,0,
53080,105,0,109,0, 6093114,0,76,0,111,
5309112,0,108,0,101, 60940,111,0,112,0,
53100,65,0,115,0, 609583,0,116,0,97,
5311115,0,105,0,103, 60960,116,0,101,0,
53120,110,0,109,0, 6097109,0,101,0,110,
5313101,0,110,0,116, 60980,116,0,95,0,
53140,95,0,50,0, 609952,0,1,252,1,
531550,0,1,221,1, 61003,1,4,1,3,
53163,1,6,1,5, 61011659,22,1,88,1,
53171532,22,1,81,1, 6102476,1660,17,1661,15,
5318223,1533,17,1534,15, 61031662,4,18,37,0,
53191121,1,-1,1,5, 610467,0,111,0,110,
53201535,20,1536,4,36, 61050,115,0,116,0,
532166,0,105,0,110, 610697,0,110,0,116,
53220,97,0,114,0, 61070,1,-1,1,5,
5323121,0,69,0,120, 61081663,20,1664,4,20,
53240,112,0,114,0, 610967,0,111,0,110,
5325101,0,115,0,115, 61100,115,0,116,0,
53260,105,0,111,0, 611197,0,110,0,116,
5327110,0,95,0,55,
53280,1,251,1,3,
53291,4,1,3,1537,
533022,1,111,1,1730,
53311538,17,1539,15,1156,
53321,-1,1,5,1540,
533320,1541,4,36,70,
53340,111,0,114,0,
533576,0,111,0,111,
53360,112,0,83,0,
5337116,0,97,0,116,
53380,101,0,109,0,
5339101,0,110,0,116,
53400,95,0,52,0, 61120,95,0,52,0,
53411,197,1,3,1, 61131,284,1,3,1,
53424,1,3,1542,22, 61142,1,1,1665,22,
53431,57,1,476,1543, 61151,120,1,477,1666,
534417,1544,15,1545,4, 611617,1667,15,1662,1,
534518,37,0,67,0, 6117-1,1,5,1668,20,
5346111,0,110,0,115, 61181669,4,20,67,0,
53470,116,0,97,0,
5348110,0,116,0,1,
5349-1,1,5,1546,20,
53501547,4,20,67,0,
5351111,0,110,0,115, 6119111,0,110,0,115,
53520,116,0,97,0, 61200,116,0,97,0,
5353110,0,116,0,95, 6121110,0,116,0,95,
53540,52,0,1,229, 61220,51,0,1,283,
53551,3,1,2,1, 61231,3,1,2,1,
53561,1548,22,1,89, 61241,1670,22,1,119,
53571,477,1549,17,1550, 61251,1231,1671,17,1672,
535815,1545,1,-1,1, 612615,1220,1,-1,1,
53595,1551,20,1552,4, 61275,1673,20,1674,4,
536020,67,0,111,0, 612836,83,0,105,0,
6129109,0,112,0,108,
61300,101,0,65,0,
6131115,0,115,0,105,
61320,103,0,110,0,
6133109,0,101,0,110,
61340,116,0,95,0,
613557,0,1,263,1,
61363,1,6,1,5,
61371675,22,1,99,1,
6138479,1676,17,1677,15,
61391662,1,-1,1,5,
61401678,20,1679,4,20,
614167,0,111,0,110,
61420,115,0,116,0,
614397,0,110,0,116,
61440,95,0,49,0,
61451,281,1,3,1,
61462,1,1,1680,22,
61471,117,1,480,1681,
614817,1682,15,1683,4,
614926,37,0,76,0,
6150105,0,115,0,116,
61510,67,0,111,0,
5361110,0,115,0,116, 6152110,0,115,0,116,
53620,97,0,110,0, 61530,97,0,110,0,
5363116,0,95,0,51, 6154116,0,1,-1,1,
53640,1,228,1,3, 61555,1684,20,1685,4,
53651,2,1,1,1553, 615628,76,0,105,0,
536622,1,88,1,1231,
53671554,17,1555,15,1098,
53681,-1,1,5,1556,
536920,1557,4,36,83,
53700,105,0,109,0,
5371112,0,108,0,101,
53720,65,0,115,0,
5373115,0,105,0,103,
53740,110,0,109,0,
5375101,0,110,0,116,
53760,95,0,57,0,
53771,208,1,3,1,
53786,1,5,1558,22,
53791,68,1,479,1559,
538017,1560,15,1545,1,
5381-1,1,5,1561,20,
53821562,4,20,67,0,
5383111,0,110,0,115,
53840,116,0,97,0,
5385110,0,116,0,95,
53860,49,0,1,226,
53871,3,1,2,1,
53881,1563,22,1,86,
53891,480,1564,17,1565,
539015,1566,4,26,37,
53910,76,0,105,0,
5392115,0,116,0,67, 6157115,0,116,0,67,
53930,111,0,110,0, 61580,111,0,110,0,
5394115,0,116,0,97, 6159115,0,116,0,97,
53950,110,0,116,0, 61600,110,0,116,0,
53961,-1,1,5,1567, 616195,0,49,0,1,
539720,1568,4,28,76, 6162285,1,3,1,4,
53980,105,0,115,0, 61631,3,1686,22,1,
5399116,0,67,0,111, 6164121,1,1485,1687,17,
54000,110,0,115,0, 61651688,15,1220,1,-1,
5401116,0,97,0,110, 61661,5,1689,20,1690,
54020,116,0,95,0, 61674,36,83,0,105,
540349,0,1,230,1, 61680,109,0,112,0,
54043,1,4,1,3, 6169108,0,101,0,65,
54051569,22,1,90,1, 61700,115,0,115,0,
54061485,1570,17,1571,15, 6171105,0,103,0,110,
54071098,1,-1,1,5, 61720,109,0,101,0,
54081572,20,1573,4,36, 6173110,0,116,0,95,
540983,0,105,0,109, 61740,50,0,1,256,
54100,112,0,108,0, 61751,3,1,4,1,
5411101,0,65,0,115, 61763,1691,22,1,92,
54120,115,0,105,0, 61771,1737,1692,16,0,
5413103,0,110,0,109, 6178299,1,1989,1038,1,
54140,101,0,110,0, 61791990,1693,17,1264,1,
5415116,0,95,0,50, 61800,1268,1,1096,1694,
54160,1,201,1,3, 618117,1695,15,1696,4,
54171,4,1,3,1574, 618226,37,0,70,0,
541822,1,61,1,1737, 6183117,0,110,0,99,
54191575,16,0,271,1, 61840,116,0,105,0,
54201989,916,1,1990,1576, 6185111,0,110,0,67,
542117,1142,1,0,1146, 61860,97,0,108,0,
54221,2664,1577,16,0, 6187108,0,1,-1,1,
5423667,1,242,1578,17, 61885,1697,20,1698,4,
54241579,15,1121,1,-1, 618928,70,0,117,0,
54251,5,1580,20,1581, 6190110,0,99,0,116,
61910,105,0,111,0,
6192110,0,67,0,97,
61930,108,0,108,0,
619495,0,49,0,1,
6195332,1,3,1,5,
61961,4,1699,22,1,
6197168,1,242,1700,17,
61981701,15,1243,1,-1,
61991,5,1702,20,1703,
54264,36,66,0,105, 62004,36,66,0,105,
54270,110,0,97,0, 62010,110,0,97,0,
5428114,0,121,0,69, 6202114,0,121,0,69,
@@ -5430,22 +6204,22 @@ public yyLSLSyntax
5430114,0,101,0,115, 6204114,0,101,0,115,
54310,115,0,105,0, 62050,115,0,105,0,
5432111,0,110,0,95, 6206111,0,110,0,95,
54330,54,0,1,250, 62070,54,0,1,305,
54341,3,1,4,1, 62081,3,1,4,1,
54353,1582,22,1,110, 62093,1704,22,1,141,
54361,478,1583,17,1584, 62101,478,1705,17,1706,
543715,1545,1,-1,1, 621115,1662,1,-1,1,
54385,1585,20,1586,4, 62125,1707,20,1708,4,
543920,67,0,111,0, 621320,67,0,111,0,
5440110,0,115,0,116, 6214110,0,115,0,116,
54410,97,0,110,0, 62150,97,0,110,0,
5442116,0,95,0,50, 6216116,0,95,0,50,
54430,1,227,1,3, 62170,1,282,1,3,
54441,2,1,1,1587, 62181,2,1,1,1709,
544522,1,87,1,1001, 621922,1,118,1,1001,
54461588,17,1589,15,1224, 62201710,17,1711,15,1347,
54471,-1,1,5,1590, 62211,-1,1,5,1712,
544820,1591,4,40,84, 622220,1713,4,40,84,
54490,121,0,112,0, 62230,121,0,112,0,
5450101,0,99,0,97, 6224101,0,99,0,97,
54510,115,0,116,0, 62250,115,0,116,0,
@@ -5454,11 +6228,11 @@ public yyLSLSyntax
5454115,0,115,0,105, 6228115,0,115,0,105,
54550,111,0,110,0, 62290,111,0,110,0,
545695,0,56,0,1, 623095,0,56,0,1,
5457275,1,3,1,5, 6231330,1,3,1,5,
54581,4,1592,22,1, 62321,4,1714,22,1,
5459135,1,1002,1593,17, 6233166,1,1002,1715,17,
54601594,15,1224,1,-1, 62341716,15,1347,1,-1,
54611,5,1595,20,1596, 62351,5,1717,20,1718,
54624,40,84,0,121, 62364,40,84,0,121,
54630,112,0,101,0, 62370,112,0,101,0,
546499,0,97,0,115, 623899,0,97,0,115,
@@ -5467,154 +6241,607 @@ public yyLSLSyntax
54670,101,0,115,0, 62410,101,0,115,0,
5468115,0,105,0,111, 6242115,0,105,0,111,
54690,110,0,95,0, 62430,110,0,95,0,
547049,0,1,268,1, 624449,0,1,323,1,
54713,1,5,1,4, 62453,1,5,1,4,
54721597,22,1,128,1, 62461719,22,1,159,1,
547312,1598,19,157,1, 624712,1720,19,166,1,
547412,1599,5,43,1, 624812,1721,5,50,1,
54751901,1600,16,0,155, 62491901,1722,16,0,164,
54761,2075,1601,16,0, 62501,2075,1723,16,0,
5477155,1,1860,821,1, 6251164,1,1860,943,1,
54781803,787,1,1804,1602, 62521803,909,1,1804,1724,
547916,0,155,1,2517, 625316,0,164,1,2518,
54801603,16,0,155,1, 62541725,16,0,164,1,
54812413,1604,16,0,155, 62552413,1726,16,0,164,
54821,2198,1605,16,0, 62561,2198,1727,16,0,
5483155,1,1873,835,1, 6257164,1,1873,958,1,
54841657,894,1,1989,916, 62581657,1016,1,2136,965,
54851,1990,1606,16,0, 62591,2032,863,1,1989,
5486155,1,31,1607,16, 62601038,1,1990,1728,16,
54870,155,1,32,1608, 62610,164,1,31,1729,
548816,0,155,1,2105, 626216,0,164,1,32,
5489814,1,2106,1609,16, 62631730,16,0,164,1,
54900,155,1,2653,1610, 62642105,936,1,2106,1731,
549116,0,155,1,2227, 626516,0,164,1,2656,
5492908,1,2337,1611,16, 62661732,16,0,282,1,
54930,155,1,2560,1612, 62672548,1733,16,0,164,
549416,0,467,1,2021, 62681,2227,1030,1,2337,
5495718,1,2458,876,1, 62691734,16,0,164,1,
54962459,882,1,2462,889, 62702556,1735,16,0,164,
54971,2136,842,1,2464, 62711,2777,1736,16,0,
5498899,1,2029,725,1, 6272164,1,2564,1737,16,
54992030,731,1,2031,736, 62730,164,1,2021,840,
55001,2032,741,1,2469, 62741,2458,998,1,2459,
55011613,16,0,454,1, 62751004,1,2462,1011,1,
55022035,752,1,2364,827, 62762572,1738,16,0,164,
55031,2039,762,1,1931, 62771,2464,1021,1,2029,
5504861,1,2041,768,1, 6278847,1,2030,853,1,
55052043,774,1,2045,779, 62792031,858,1,2577,1739,
55061,1775,1614,16,0, 628016,0,164,1,2469,
5507155,1,2033,746,1, 62811740,16,0,520,1,
55082037,757,1,1574,799, 62822035,874,1,2364,949,
55091,1958,1615,16,0, 62831,2039,884,1,1931,
5510155,1,13,1616,19, 6284983,1,2041,890,1,
5511448,1,13,1617,5, 62852043,896,1,2045,901,
551234,1,1860,821,1, 62861,2592,1741,16,0,
55131803,787,1,2519,1618, 6287164,1,1775,1742,16,
551417,1619,15,1620,4, 62880,164,1,2033,868,
551522,37,0,83,0, 62891,2037,879,1,1574,
6290921,1,1958,1743,16,
62910,164,1,2533,1744,
629216,0,164,1,13,
62931745,19,508,1,13,
62941746,5,55,1,2643,
62951747,17,1748,15,1749,
62964,20,37,0,83,
62970,116,0,97,0,
6298116,0,101,0,66,
62990,111,0,100,0,
6300121,0,1,-1,1,
63015,1750,20,1751,4,
630222,83,0,116,0,
630397,0,116,0,101,
63040,66,0,111,0,
6305100,0,121,0,95,
63060,56,0,1,187,
63071,3,1,3,1,
63082,1752,22,1,22,
63091,2644,1753,17,1754,
631015,1749,1,-1,1,
63115,1755,20,1756,4,
631222,83,0,116,0,
631397,0,116,0,101,
63140,66,0,111,0,
6315100,0,121,0,95,
63160,54,0,1,185,
63171,3,1,3,1,
63182,1757,22,1,20,
63191,1860,943,1,1803,
6320909,1,2520,1758,17,
63211759,15,1760,4,46,
632237,0,75,0,101,
63230,121,0,73,0,
6324110,0,116,0,73,
63250,110,0,116,0,
632665,0,114,0,103,
63270,83,0,116,0,
632897,0,116,0,101,
63290,69,0,118,0,
6330101,0,110,0,116,
63310,1,-1,1,5,
63321761,20,1762,4,48,
633375,0,101,0,121,
63340,73,0,110,0,
6335116,0,73,0,110,
63360,116,0,65,0,
6337114,0,103,0,83,
63380,116,0,97,0,
6339116,0,101,0,69,
63400,118,0,101,0,
6341110,0,116,0,95,
63420,49,0,1,203,
63431,3,1,6,1,
63445,1763,22,1,38,
63451,2413,1764,16,0,
6346506,1,1873,958,1,
63471657,1016,1,2639,1765,
634817,1766,15,1749,1,
6349-1,1,5,1767,20,
63501768,4,24,83,0,
6351116,0,97,0,116,
63520,101,0,66,0,
6353111,0,100,0,121,
63540,95,0,49,0,
635554,0,1,195,1,
63563,1,3,1,2,
63571769,22,1,30,1,
63582640,1770,17,1771,15,
63591749,1,-1,1,5,
63601772,20,1773,4,24,
636183,0,116,0,97,
63620,116,0,101,0,
636366,0,111,0,100,
63640,121,0,95,0,
636549,0,52,0,1,
6366193,1,3,1,3,
63671,2,1774,22,1,
636828,1,2641,1775,17,
63691776,15,1749,1,-1,
63701,5,1777,20,1778,
63714,24,83,0,116,
63720,97,0,116,0,
6373101,0,66,0,111,
63740,100,0,121,0,
637595,0,49,0,50,
63760,1,191,1,3,
63771,3,1,2,1779,
637822,1,26,1,2642,
63791780,17,1781,15,1749,
63801,-1,1,5,1782,
638120,1783,4,24,83,
63820,116,0,97,0,
6383116,0,101,0,66,
63840,111,0,100,0,
6385121,0,95,0,49,
63860,48,0,1,189,
63871,3,1,3,1,
63882,1784,22,1,24,
63891,1989,1038,1,2535,
63901785,17,1786,15,1787,
63914,46,37,0,73,
63920,110,0,116,0,
639386,0,101,0,99,
63940,86,0,101,0,
639599,0,65,0,114,
63960,103,0,83,0,
5516116,0,97,0,116, 6397116,0,97,0,116,
55170,101,0,69,0, 63980,101,0,69,0,
5518118,0,101,0,110, 6399118,0,101,0,110,
55190,116,0,1,-1, 64000,116,0,1,-1,
55201,5,1621,20,1622, 64011,5,1788,20,1789,
55214,24,83,0,116, 64024,48,73,0,110,
55220,97,0,116,0, 64030,116,0,86,0,
5523101,0,69,0,118, 6404101,0,99,0,86,
55240,101,0,110,0, 64050,101,0,99,0,
5525116,0,95,0,49, 640665,0,114,0,103,
55260,1,158,1,3, 64070,83,0,116,0,
55271,6,1,5,1623, 640897,0,116,0,101,
552822,1,17,1,2521, 64090,69,0,118,0,
55291624,16,0,460,1, 6410101,0,110,0,116,
55302413,1625,16,0,446, 64110,95,0,49,0,
55311,1873,835,1,1657, 64121,202,1,3,1,
5532894,1,1989,916,1, 64136,1,5,1790,22,
553332,1626,16,0,449, 64141,37,1,2645,1791,
55341,2105,814,1,2364, 641517,1792,15,1749,1,
5535827,1,2227,908,1, 6416-1,1,5,1793,20,
55361574,799,1,2557,1627, 64171794,4,22,83,0,
553717,1628,15,1629,4,
553820,37,0,83,0,
5539116,0,97,0,116, 6418116,0,97,0,116,
55400,101,0,66,0, 64190,101,0,66,0,
5541111,0,100,0,121, 6420111,0,100,0,121,
55420,1,-1,1,5, 64210,95,0,52,0,
55431630,20,1631,4,22, 64221,183,1,3,1,
64233,1,2,1795,22,
64241,18,1,2646,1796,
642517,1797,15,1749,1,
6426-1,1,5,1798,20,
64271799,4,22,83,0,
6428116,0,97,0,116,
64290,101,0,66,0,
6430111,0,100,0,121,
64310,95,0,50,0,
64321,181,1,3,1,
64333,1,2,1800,22,
64341,16,1,2037,879,
64351,32,1801,16,0,
6436513,1,2649,1802,17,
64371803,15,1749,1,-1,
64381,5,1804,20,1805,
64394,24,83,0,116,
64400,97,0,116,0,
6441101,0,66,0,111,
64420,100,0,121,0,
644395,0,49,0,51,
64440,1,192,1,3,
64451,2,1,1,1806,
644622,1,27,1,2650,
64471807,17,1808,15,1749,
64481,-1,1,5,1809,
644920,1810,4,24,83,
64500,116,0,97,0,
6451116,0,101,0,66,
64520,111,0,100,0,
6453121,0,95,0,49,
64540,49,0,1,190,
64551,3,1,2,1,
64561,1811,22,1,25,
64571,2651,1812,17,1813,
645815,1749,1,-1,1,
64595,1814,20,1815,4,
646022,83,0,116,0,
646197,0,116,0,101,
64620,66,0,111,0,
6463100,0,121,0,95,
64640,57,0,1,188,
64651,3,1,2,1,
64661,1816,22,1,23,
64671,2652,1817,17,1818,
646815,1749,1,-1,1,
64695,1819,20,1820,4,
647022,83,0,116,0,
647197,0,116,0,101,
64720,66,0,111,0,
6473100,0,121,0,95,
64740,55,0,1,186,
64751,3,1,2,1,
64761,1821,22,1,21,
64771,2653,1822,17,1823,
647815,1749,1,-1,1,
64795,1824,20,1825,4,
648022,83,0,116,0,
648197,0,116,0,101,
64820,66,0,111,0,
6483100,0,121,0,95,
64840,53,0,1,184,
64851,3,1,2,1,
64861,1826,22,1,19,
64871,2654,1827,17,1828,
648815,1749,1,-1,1,
64895,1829,20,1830,4,
649022,83,0,116,0,
649197,0,116,0,101,
64920,66,0,111,0,
6493100,0,121,0,95,
64940,51,0,1,182,
64951,3,1,2,1,
64961,1831,22,1,17,
64971,2655,1832,17,1833,
649815,1749,1,-1,1,
64995,1834,20,1835,4,
650022,83,0,116,0,
650197,0,116,0,101,
65020,66,0,111,0,
6503100,0,121,0,95,
65040,49,0,1,180,
65051,3,1,2,1,
65061,1836,22,1,15,
65071,2574,1837,17,1838,
650815,1839,4,34,37,
65090,75,0,101,0,
6510121,0,65,0,114,
65110,103,0,83,0,
6512116,0,97,0,116,
65130,101,0,69,0,
6514118,0,101,0,110,
65150,116,0,1,-1,
65161,5,1840,20,1841,
65174,36,75,0,101,
65180,121,0,65,0,
6519114,0,103,0,83,
65200,116,0,97,0,
6521116,0,101,0,69,
65220,118,0,101,0,
6523110,0,116,0,95,
65240,49,0,1,198,
65251,3,1,6,1,
65265,1842,22,1,33,
65271,2550,1843,17,1844,
652815,1845,4,46,37,
65290,73,0,110,0,
6530116,0,82,0,111,
65310,116,0,82,0,
6532111,0,116,0,65,
65330,114,0,103,0,
554483,0,116,0,97, 653483,0,116,0,97,
55450,116,0,101,0, 65350,116,0,101,0,
554666,0,111,0,100, 653669,0,118,0,101,
55470,121,0,95,0, 65370,110,0,116,0,
554850,0,1,157,1, 65381,-1,1,5,1846,
55493,1,3,1,2, 653920,1847,4,48,73,
55501632,22,1,16,1, 65400,110,0,116,0,
55512559,1633,17,1634,15, 654182,0,111,0,116,
55521629,1,-1,1,5, 65420,82,0,111,0,
55531635,20,1636,4,22, 6543116,0,65,0,114,
65440,103,0,83,0,
6545116,0,97,0,116,
65460,101,0,69,0,
6547118,0,101,0,110,
65480,116,0,95,0,
654949,0,1,201,1,
65503,1,6,1,5,
65511848,22,1,36,1,
65522227,1030,1,1574,921,
65531,2558,1849,17,1850,
655415,1851,4,40,37,
65550,86,0,101,0,
655699,0,116,0,111,
65570,114,0,65,0,
6558114,0,103,0,83,
65590,116,0,97,0,
6560116,0,101,0,69,
65610,118,0,101,0,
6562110,0,116,0,1,
6563-1,1,5,1852,20,
65641853,4,42,86,0,
6565101,0,99,0,116,
65660,111,0,114,0,
656765,0,114,0,103,
65680,83,0,116,0,
656997,0,116,0,101,
65700,69,0,118,0,
6571101,0,110,0,116,
65720,95,0,49,0,
65731,200,1,3,1,
65746,1,5,1854,22,
65751,35,1,2566,1855,
657617,1856,15,1857,4,
657734,37,0,73,0,
6578110,0,116,0,65,
65790,114,0,103,0,
555483,0,116,0,97, 658083,0,116,0,97,
55550,116,0,101,0, 65810,116,0,101,0,
555666,0,111,0,100, 658269,0,118,0,101,
55570,121,0,95,0, 65830,110,0,116,0,
555849,0,1,156,1, 65841,-1,1,5,1858,
55593,1,2,1,1, 658520,1859,4,36,73,
55601637,22,1,15,1, 65860,110,0,116,0,
55612021,718,1,2458,876,
55621,2459,882,1,2462,
5563889,1,2136,842,1,
55642464,899,1,2029,725,
55651,2030,731,1,2031,
5566736,1,2032,741,1,
55672033,746,1,2035,752,
55681,2037,757,1,2039,
5569762,1,1931,861,1,
55702041,768,1,2043,774,
55711,2045,779,1,2597,
55721638,16,0,639,1,
557314,1639,19,144,1,
557414,1640,5,105,1,
55752515,1641,16,0,142,
55761,1011,1102,1,1514,
55771108,1,9,1113,1,
557810,1642,17,1643,15,
55791644,4,48,37,0,
558065,0,114,0,103, 658765,0,114,0,103,
55810,117,0,109,0, 65880,83,0,116,0,
658997,0,116,0,101,
65900,69,0,118,0,
5582101,0,110,0,116, 6591101,0,110,0,116,
65920,95,0,49,0,
65931,199,1,3,1,
65946,1,5,1860,22,
65951,34,1,2458,998,
65961,2459,1004,1,2462,
65971011,1,2136,965,1,
65982464,1021,1,2029,847,
65991,2030,853,1,2031,
6600858,1,2032,863,1,
66012033,868,1,2579,1861,
660217,1862,15,1863,4,
660336,37,0,86,0,
6604111,0,105,0,100,
66050,65,0,114,0,
6606103,0,83,0,116,
66070,97,0,116,0,
6608101,0,69,0,118,
66090,101,0,110,0,
6610116,0,1,-1,1,
66115,1864,20,1865,4,
661238,86,0,111,0,
6613105,0,100,0,65,
66140,114,0,103,0,
661583,0,116,0,97,
66160,116,0,101,0,
661769,0,118,0,101,
66180,110,0,116,0,
661995,0,49,0,1,
6620197,1,3,1,5,
66211,4,1866,22,1,
662232,1,2035,874,1,
66232364,949,1,2039,884,
66241,1931,983,1,2041,
6625890,1,2021,840,1,
66262043,896,1,2045,901,
66271,2700,1867,16,0,
6628769,1,2594,1868,17,
66291869,15,1870,4,22,
663037,0,83,0,116,
66310,97,0,116,0,
6632101,0,69,0,118,
66330,101,0,110,0,
6634116,0,1,-1,1,
66355,1871,20,1872,4,
663624,83,0,116,0,
663797,0,116,0,101,
66380,69,0,118,0,
6639101,0,110,0,116,
66400,95,0,49,0,
66411,196,1,3,1,
66426,1,5,1873,22,
66431,31,1,2596,1874,
664416,0,662,1,2648,
66451875,17,1876,15,1749,
66461,-1,1,5,1877,
664720,1878,4,24,83,
66480,116,0,97,0,
6649116,0,101,0,66,
66500,111,0,100,0,
6651121,0,95,0,49,
66520,53,0,1,194,
66531,3,1,2,1,
66541,1879,22,1,29,
66551,2105,936,1,14,
66561880,19,144,1,14,
66571881,5,115,1,2512,
66581882,17,1883,15,1884,
66594,30,37,0,73,
66600,110,0,116,0,
666168,0,101,0,99,
66620,108,0,97,0,
6663114,0,97,0,116,
66640,105,0,111,0,
6665110,0,1,-1,1,
66665,1885,20,1886,4,
666732,73,0,110,0,
6668116,0,68,0,101,
66690,99,0,108,0,
667097,0,114,0,97,
66710,116,0,105,0,
6672111,0,110,0,95,
66730,49,0,1,214,
66741,3,1,3,1,
66752,1887,22,1,50,
66761,2513,1888,16,0,
6677481,1,1260,1218,1,
66781011,1224,1,1514,1230,
66791,9,1235,1,10,
66801889,17,1890,15,1891,
66814,48,37,0,65,
66820,114,0,103,0,
6683117,0,109,0,101,
66840,110,0,116,0,
668568,0,101,0,99,
66860,108,0,97,0,
6687114,0,97,0,116,
66880,105,0,111,0,
6689110,0,76,0,105,
66900,115,0,116,0,
66911,-1,1,5,140,
66921,0,1,0,1892,
669322,1,39,1,262,
66941241,1,1267,1247,1,
66952524,1893,16,0,492,
66961,1521,1252,1,1773,
66971894,16,0,151,1,
66982527,1895,17,1896,15,
66991897,4,30,37,0,
670086,0,101,0,99,
55830,68,0,101,0, 67010,68,0,101,0,
558499,0,108,0,97, 670299,0,108,0,97,
55850,114,0,97,0, 67030,114,0,97,0,
5586116,0,105,0,111, 6704116,0,105,0,111,
55870,110,0,76,0, 67050,110,0,1,-1,
5588105,0,115,0,116, 67061,5,1898,20,1899,
55890,1,-1,1,5, 67074,32,86,0,101,
5590140,1,0,1,0, 67080,99,0,68,0,
55911645,22,1,18,1, 6709101,0,99,0,108,
5592262,1119,1,1267,1125, 67100,97,0,114,0,
55931,481,1646,17,1647, 671197,0,116,0,105,
559415,1648,4,26,37, 67120,111,0,110,0,
671395,0,49,0,1,
6714215,1,3,1,3,
67151,2,1900,22,1,
671651,1,2528,1901,16,
67170,498,1,19,1269,
67181,20,1902,16,0,
6719142,1,2281,1276,1,
6720525,1339,1,2539,1903,
672116,0,510,1,30,
67221904,17,1905,15,1891,
67231,-1,1,5,1906,
672420,1907,4,50,65,
67250,114,0,103,0,
6726117,0,109,0,101,
67270,110,0,116,0,
672868,0,101,0,99,
67290,108,0,97,0,
6730114,0,97,0,116,
67310,105,0,111,0,
6732110,0,76,0,105,
67330,115,0,116,0,
673495,0,50,0,1,
6735205,1,3,1,4,
67361,3,1908,22,1,
673741,1,1002,1715,1,
67382542,1909,17,1910,15,
67391911,4,30,37,0,
674082,0,111,0,116,
67410,68,0,101,0,
674299,0,108,0,97,
67430,114,0,97,0,
6744116,0,105,0,111,
67450,110,0,1,-1,
67461,5,1912,20,1913,
67474,32,82,0,111,
67480,116,0,68,0,
6749101,0,99,0,108,
67500,97,0,114,0,
675197,0,116,0,105,
67520,111,0,110,0,
675395,0,49,0,1,
6754216,1,3,1,3,
67551,2,1914,22,1,
675652,1,2543,1915,16,
67570,514,1,40,1300,
67581,41,1916,17,1917,
675915,1918,4,26,37,
55950,65,0,114,0, 67600,65,0,114,0,
5596103,0,117,0,109, 6761103,0,117,0,109,
55970,101,0,110,0, 67620,101,0,110,0,
5598116,0,76,0,105, 6763116,0,76,0,105,
55990,115,0,116,0, 67640,115,0,116,0,
56001,-1,1,5,1649, 67651,-1,1,5,709,
560120,1650,4,28,65, 67661,0,1,0,1919,
676722,1,169,1,42,
67681920,17,1921,15,1922,
67694,38,37,0,69,
67700,120,0,112,0,
6771114,0,101,0,115,
67720,115,0,105,0,
6773111,0,110,0,65,
56020,114,0,103,0, 67740,114,0,103,0,
5603117,0,109,0,101, 6775117,0,109,0,101,
56040,110,0,116,0, 67760,110,0,116,0,
560576,0,105,0,115, 67771,-1,1,5,1923,
56060,116,0,95,0, 677820,1924,4,40,69,
560749,0,1,278,1, 67790,120,0,112,0,
56083,1,2,1,1, 6780114,0,101,0,115,
56091651,22,1,139,1, 67810,115,0,105,0,
56101521,1130,1,1773,1652, 6782111,0,110,0,65,
561116,0,148,1,19, 67830,114,0,103,0,
56121147,1,20,1653,16, 6784117,0,109,0,101,
56130,142,1,2281,1154, 67850,110,0,116,0,
56141,525,1216,1,30, 678695,0,49,0,1,
56151654,17,1655,15,1644, 6787335,1,3,1,2,
56161,-1,1,5,1656, 67881,1,1925,22,1,
561720,1657,4,50,65, 6789172,1,44,1306,1,
679047,1307,1,48,1313,
67911,49,1319,1,50,
67921324,1,51,1329,1,
6793283,1295,1,305,1334,
67941,63,1345,1,66,
67951351,1,67,1356,1,
67961478,1575,1,69,1366,
67971,70,1371,1,2581,
67981926,17,1927,15,1891,
67991,-1,1,5,140,
68001,0,1,0,1892,
68011,68,1361,1,74,
68021376,1,1013,1381,1,
68032335,1928,16,0,151,
68041,1332,1386,1,1048,
68051462,1,2590,1929,16,
68060,142,1,82,1403,
68071,1296,1290,1,1341,
68081420,1,328,1425,1,
68091303,1430,1,1096,1694,
68101,93,1435,1,1550,
68111440,1,352,1467,1,
68122775,1930,16,0,142,
68131,107,1455,1,1114,
68141461,1,1370,1570,1,
6815118,1473,1,1123,1478,
68161,371,1483,1,1377,
68171489,1,375,1494,1,
6818377,1499,1,827,1448,
68191,380,1509,1,883,
68201515,1,373,1527,1,
6821130,1532,1,379,1504,
68221,143,1537,1,1152,
68231543,1,387,1931,16,
68240,643,1,1406,1548,
68251,1159,1555,1,157,
68261560,1,1413,1565,1,
68271665,1591,1,412,1932,
682816,0,680,1,1094,
68291933,16,0,711,1,
6830172,1586,1,2766,1934,
683117,1935,15,1891,1,
6832-1,1,5,140,1,
68330,1,0,1892,1,
68341188,1596,1,437,1936,
683516,0,755,1,1442,
68361601,1,1694,1937,16,
68370,151,1,942,1607,
68381,1195,1613,1,1449,
68391618,1,1701,1623,1,
6840447,1628,1,188,1635,
68411,205,1640,1,2467,
68421938,17,1939,15,1891,
68431,-1,1,5,1940,
684420,1941,4,50,65,
56180,114,0,103,0, 68450,114,0,103,0,
5619117,0,109,0,101, 6846117,0,109,0,101,
56200,110,0,116,0, 68470,110,0,116,0,
@@ -5624,2837 +6851,3037 @@ public yyLSLSyntax
56240,105,0,111,0, 68510,105,0,111,0,
5625110,0,76,0,105, 6852110,0,76,0,105,
56260,115,0,116,0, 68530,115,0,116,0,
562795,0,50,0,1, 685495,0,49,0,1,
5628160,1,3,1,4, 6855204,1,3,1,2,
56291,3,1658,22,1, 68561,1,1942,22,1,
563020,1,283,1172,1, 685740,1,461,1943,16,
563140,1177,1,41,1659, 68580,711,1,464,1944,
563217,1660,15,1648,1, 685917,1945,15,1918,1,
5633-1,1,5,601,1, 6860-1,1,5,1946,20,
56340,1,0,1661,22, 68611947,4,28,65,0,
56351,138,1,42,1662,
563617,1663,15,1664,4,
563738,37,0,69,0,
5638120,0,112,0,114,
56390,101,0,115,0,
5640115,0,105,0,111,
56410,110,0,65,0,
5642114,0,103,0,117,
56430,109,0,101,0,
5644110,0,116,0,1,
5645-1,1,5,1665,20,
56461666,4,40,69,0,
5647120,0,112,0,114,
56480,101,0,115,0,
5649115,0,105,0,111,
56500,110,0,65,0,
5651114,0,103,0,117, 6862114,0,103,0,117,
56520,109,0,101,0, 68630,109,0,101,0,
5653110,0,116,0,95, 6864110,0,116,0,76,
56540,49,0,1,280, 68650,105,0,115,0,
56551,3,1,2,1, 6866116,0,95,0,50,
56561,1667,22,1,141, 68670,1,334,1,3,
56571,44,1183,1,1260, 68681,4,1,3,1948,
56581096,1,47,1184,1, 686922,1,171,1,1224,
565948,1190,1,49,1196, 68701645,1,223,1650,1,
56601,50,1201,1,51, 68711730,1655,1,476,1660,
56611206,1,305,1211,1, 68721,477,1666,1,1231,
566263,1222,1,66,1228, 68731671,1,479,1676,1,
56631,67,1233,1,1478, 6874480,1681,1,1485,1687,
56641458,1,69,1243,1, 68751,459,1949,17,1950,
566570,1248,1,68,1238, 687615,1918,1,-1,1,
56661,74,1253,1,1013, 68775,709,1,0,1,
56671258,1,2335,1668,16, 68780,1919,1,242,1700,
56680,148,1,1332,1263, 68791,478,1705,1,481,
56691,1048,1344,1,82, 68801951,17,1952,15,1918,
56701280,1,1296,1167,1, 68811,-1,1,5,1953,
56711341,1297,1,328,1302, 688220,1954,4,28,65,
56721,1303,1307,1,1096, 68830,114,0,103,0,
56731312,1,93,1318,1, 6884117,0,109,0,101,
56741550,1323,1,352,1349, 68850,110,0,116,0,
56751,107,1338,1,1114, 688676,0,105,0,115,
56761343,1,1370,1453,1, 68870,116,0,95,0,
5677118,1355,1,1123,1360, 688849,0,1,333,1,
56781,371,1365,1,1377, 68893,1,2,1,1,
56791371,1,375,1376,1, 68901955,22,1,170,1,
5680377,1381,1,379,1386, 68911001,1710,1,2508,1956,
56811,380,1391,1,883, 689217,1957,15,1958,4,
56821397,1,2642,1669,17, 689330,37,0,75,0,
56831670,15,1644,1,-1, 6894101,0,121,0,68,
56841,5,140,1,0, 68950,101,0,99,0,
56851,0,1645,1,373, 6896108,0,97,0,114,
56861409,1,130,1414,1, 68970,97,0,116,0,
56872651,1671,16,0,142, 6898105,0,111,0,110,
56881,143,1419,1,1152, 68990,1,-1,1,5,
56891426,1,387,1672,16, 69001959,20,1960,4,32,
56900,555,1,1406,1431, 690175,0,101,0,121,
56911,1159,1438,1,157,
56921443,1,1413,1448,1,
56931665,1474,1,412,1673,
569416,0,576,1,1094,
56951674,16,0,603,1,
5696172,1469,1,827,1331,
56971,1188,1479,1,437,
56981675,16,0,650,1,
56991442,1484,1,1694,1676,
570016,0,148,1,942,
57011490,1,1195,1496,1,
57021449,1501,1,1701,1506,
57031,447,1511,1,188,
57041518,1,205,1523,1,
57052467,1677,17,1678,15,
57061644,1,-1,1,5,
57071679,20,1680,4,50,
570865,0,114,0,103,
57090,117,0,109,0,
5710101,0,110,0,116,
57110,68,0,101,0, 69020,68,0,101,0,
571299,0,108,0,97, 690399,0,108,0,97,
57130,114,0,97,0, 69040,114,0,97,0,
5714116,0,105,0,111, 6905116,0,105,0,111,
57150,110,0,76,0, 69060,110,0,95,0,
5716105,0,115,0,116, 690749,0,1,213,1,
57170,95,0,49,0, 69083,1,3,1,2,
57181,159,1,3,1, 69091961,22,1,49,1,
57192,1,1,1681,22, 69102509,1962,16,0,475,
57201,19,1,461,1682, 69111,15,1963,19,334,
572116,0,603,1,464, 69121,15,1964,5,6,
57221683,17,1684,15,1648, 69131,1114,1965,16,0,
57231,-1,1,5,1685, 6914332,1,1621,1966,16,
572420,1686,4,28,65, 69150,754,1,2781,1967,
691616,0,795,1,40,
69171968,16,0,639,1,
691819,1269,1,9,1235,
69191,16,1969,19,136,
69201,16,1970,5,146,
69211,2765,1971,16,0,
6922784,1,256,1972,16,
69230,206,1,1261,1973,
692416,0,206,1,509,
69251974,16,0,206,1,
69269,1975,16,0,134,
69271,2521,1976,16,0,
6928490,1,2021,840,1,
69291775,1977,16,0,206,
69301,2029,847,1,2030,
6931853,1,2031,858,1,
69322032,863,1,2033,868,
69331,277,1978,16,0,
6934206,1,2035,874,1,
69352037,879,1,2039,884,
69361,32,1979,16,0,
6937206,1,2041,890,1,
69382293,1980,16,0,206,
69391,2043,896,1,2045,
6940901,1,40,1981,16,
69410,185,1,41,1982,
694216,0,206,1,1297,
69431983,16,0,206,1,
694443,1984,16,0,206,
69451,44,1985,16,0,
6946185,1,1803,909,1,
69471804,1986,16,0,206,
69481,299,1987,16,0,
6949206,1,2480,1988,17,
69501989,15,1990,4,24,
695137,0,73,0,110,
69520,116,0,65,0,
6953114,0,103,0,69,
69540,118,0,101,0,
6955110,0,116,0,1,
6956-1,1,5,1991,20,
69571992,4,26,73,0,
6958110,0,116,0,65,
57250,114,0,103,0, 69590,114,0,103,0,
5726117,0,109,0,101, 696069,0,118,0,101,
57270,110,0,116,0, 69610,110,0,116,0,
572876,0,105,0,115, 696295,0,55,0,1,
57290,116,0,95,0, 6963367,1,3,1,2,
573050,0,1,279,1, 69641,1,1993,22,1,
57313,1,4,1,3, 6965204,1,52,1994,16,
57321687,22,1,140,1, 69660,206,1,2484,1995,
57331224,1528,1,223,1533, 696717,1996,15,1990,1,
57341,1730,1538,1,476, 6968-1,1,5,1997,20,
57351543,1,477,1549,1, 69691998,4,26,73,0,
57361231,1554,1,479,1559, 6970110,0,116,0,65,
57371,480,1564,1,1485, 69710,114,0,103,0,
57381570,1,459,1688,17, 697269,0,118,0,101,
57391689,15,1648,1,-1, 69730,110,0,116,0,
57401,5,601,1,0, 697495,0,51,0,1,
57411,0,1661,1,242, 6975363,1,3,1,2,
57421578,1,478,1583,1, 69761,1,1999,22,1,
57432506,1690,17,1691,15, 6977200,1,2567,2000,16,
57441644,1,-1,1,5, 69780,750,1,1515,2001,
5745140,1,0,1,0, 697916,0,206,1,2318,
57461645,1,1001,1588,1, 69802002,16,0,206,1,
57471002,1593,1,15,1692, 69812491,2003,17,2004,15,
574819,257,1,15,1693, 69822005,4,26,37,0,
57495,6,1,1114,1694, 698386,0,111,0,105,
575016,0,299,1,1621, 69840,100,0,65,0,
57511695,16,0,649,1, 6985114,0,103,0,69,
57522657,1696,16,0,255, 69860,118,0,101,0,
57531,40,1697,16,0, 6987110,0,116,0,1,
5754552,1,19,1147,1, 6988-1,1,5,2006,20,
57559,1113,1,16,1698, 69892007,4,28,86,0,
575619,136,1,16,1699, 6990111,0,105,0,100,
57575,139,1,256,1700, 69910,65,0,114,0,
575816,0,187,1,1261, 6992103,0,69,0,118,
57591701,16,0,187,1,
5760509,1702,16,0,187,
57611,9,1703,16,0,
5762134,1,2021,718,1,
57631775,1704,16,0,187,
57641,2029,725,1,2030,
5765731,1,2031,736,1,
57662032,741,1,2033,746,
57671,277,1705,16,0,
5768187,1,2035,752,1,
57692037,757,1,2039,762,
57701,32,1706,16,0,
5771187,1,2041,768,1,
57722293,1707,16,0,187,
57731,2043,774,1,2045,
5774779,1,40,1708,16,
57750,166,1,41,1709,
577616,0,187,1,1297,
57771710,16,0,187,1,
577843,1711,16,0,187,
57791,44,1712,16,0,
5780166,1,1803,787,1,
57811804,1713,16,0,187,
57821,299,1714,16,0,
5783187,1,2480,1715,17,
57841716,15,1717,4,12,
578537,0,69,0,118,
57860,101,0,110,0, 69930,101,0,110,0,
5787116,0,1,-1,1, 6994116,0,95,0,54,
57885,1718,20,1719,4, 69950,1,356,1,3,
578916,69,0,118,0, 69961,2,1,1,2008,
5790101,0,110,0,116, 699722,1,193,1,62,
57910,95,0,50,0, 69982009,16,0,228,1,
579253,0,1,312,1, 699963,2010,16,0,185,
57933,1,2,1,1, 70001,2495,2011,17,2012,
57941720,22,1,173,1, 700115,2005,1,-1,1,
579552,1721,16,0,187, 70025,2013,20,2014,4,
57961,2484,1722,17,1723, 700328,86,0,111,0,
579715,1717,1,-1,1, 7004105,0,100,0,65,
57985,1724,20,1725,4, 70050,114,0,103,0,
579916,69,0,118,0, 700669,0,118,0,101,
5800101,0,110,0,116, 70070,110,0,116,0,
58010,95,0,50,0, 700895,0,50,0,1,
580249,0,1,308,1, 7009352,1,3,1,2,
58033,1,2,1,1, 70101,1,2015,22,1,
58041726,22,1,169,1, 7011189,1,2575,2016,16,
58051515,1727,16,0,187, 70120,759,1,2075,2017,
58061,2318,1728,16,0, 701316,0,206,1,1574,
5807187,1,2491,1729,17, 7014921,1,1479,2018,16,
58081730,15,1717,1,-1, 70150,206,1,2580,2019,
58091,5,1731,20,1732, 701616,0,352,1,71,
58104,16,69,0,118, 70172020,16,0,206,1,
70181658,2021,16,0,790,
70191,1833,2022,16,0,
7020321,1,1834,2023,16,
70210,206,1,2337,2024,
702216,0,206,1,79,
70232025,16,0,206,1,
70241335,2026,16,0,206,
70251,322,2027,16,0,
7026206,1,76,2028,16,
70270,206,1,85,2029,
702816,0,206,1,89,
70292030,16,0,206,1,
7030346,2031,16,0,206,
70311,97,2032,16,0,
7032206,1,2106,2033,16,
70330,206,1,102,2034,
703416,0,206,1,1860,
7035943,1,2458,998,1,
70362364,949,1,2536,2035,
703716,0,633,1,2782,
70382036,16,0,206,1,
70391990,2037,16,0,206,
70401,112,2038,16,0,
7041206,1,1117,2039,16,
70420,206,1,1873,958,
70431,1875,2040,16,0,
7044436,1,1876,2041,16,
70450,206,1,2551,2042,
704616,0,642,1,124,
70472043,16,0,206,1,
70482478,2044,17,2045,15,
70491990,1,-1,1,5,
70502046,20,2047,4,26,
705173,0,110,0,116,
70520,65,0,114,0,
7053103,0,69,0,118,
58110,101,0,110,0, 70540,101,0,110,0,
5812116,0,95,0,49, 7055116,0,95,0,57,
58130,52,0,1,301, 70560,1,369,1,3,
58141,3,1,2,1, 70571,2,1,1,2048,
58151,1733,22,1,162, 705822,1,206,1,2136,
58161,62,1734,16,0, 7059965,1,2559,2049,16,
5817202,1,63,1735,16, 70600,536,1,525,2050,
58180,166,1,2495,1736, 706116,0,206,1,137,
581917,1737,15,1717,1, 70622051,16,0,206,1,
5820-1,1,5,1738,20, 7063381,2052,16,0,206,
58211739,4,16,69,0, 70641,1901,2053,16,0,
5822118,0,101,0,110, 7065206,1,1153,2054,16,
58230,116,0,95,0, 70660,206,1,151,2055,
582449,0,48,0,1, 706716,0,206,1,1407,
5825297,1,3,1,2, 70682056,16,0,206,1,
58261,1,1740,22,1, 70691659,2057,16,0,206,
5827158,1,2075,1741,16, 70701,2413,2058,16,0,
58280,187,1,1574,799, 7071206,1,406,2059,16,
58291,1479,1742,16,0, 70720,206,1,1371,2060,
5830187,1,71,1743,16, 707316,0,206,1,2105,
58310,187,1,1658,1744, 7074936,1,166,2061,16,
583216,0,672,1,1833, 70750,206,1,1622,2062,
58331745,16,0,288,1, 707616,0,206,1,1931,
58341834,1746,16,0,187, 7077983,1,1932,2063,16,
58351,2337,1747,16,0, 70780,525,1,1933,2064,
5836187,1,79,1748,16, 707916,0,206,1,431,
58370,187,1,1335,1749, 70802065,16,0,206,1,
583816,0,187,1,322, 70811585,2066,16,0,206,
58391750,16,0,187,1, 70821,182,2067,16,0,
584076,1751,16,0,187, 7083206,1,1189,2068,16,
58411,85,1752,16,0, 70840,206,1,1443,2069,
5842187,1,89,1753,16, 708516,0,206,1,1695,
58430,187,1,346,1754, 70862070,16,0,206,1,
584416,0,187,1,97, 70872198,2071,16,0,206,
58451755,16,0,187,1, 70881,447,2072,16,0,
58462106,1756,16,0,187, 7089206,1,199,2073,16,
58471,102,1757,16,0, 70900,206,1,2459,1004,
5848187,1,1860,821,1, 70911,1958,2074,16,0,
58492458,876,1,2364,827, 7092206,1,2462,1011,1,
58501,1990,1758,16,0, 70931657,1016,1,2464,1021,
5851187,1,112,1759,16, 70941,459,2075,16,0,
58520,187,1,1117,1760, 7095206,1,462,2076,16,
585316,0,187,1,1873, 70960,206,1,2471,2077,
5854835,1,1875,1761,16, 709717,2078,15,2079,4,
58550,400,1,1876,1762, 709836,37,0,75,0,
585616,0,187,1,124, 7099101,0,121,0,73,
58571763,16,0,187,1, 71000,110,0,116,0,
58582478,1764,17,1765,15, 710173,0,110,0,116,
58591717,1,-1,1,5, 71020,65,0,114,0,
58601766,20,1767,4,16, 7103103,0,69,0,118,
71040,101,0,110,0,
7105116,0,1,-1,1,
71065,2080,20,2081,4,
710738,75,0,101,0,
7108121,0,73,0,110,
71090,116,0,73,0,
7110110,0,116,0,65,
71110,114,0,103,0,
586169,0,118,0,101, 711269,0,118,0,101,
58620,110,0,116,0, 71130,110,0,116,0,
586395,0,50,0,55, 711495,0,49,0,1,
58640,1,314,1,3, 7115376,1,3,1,2,
58651,2,1,1,1768, 71161,1,2082,22,1,
586622,1,175,1,2136, 7117213,1,2472,2083,17,
5867842,1,381,1769,16, 71182084,15,2085,4,36,
58680,187,1,2641,1770, 711937,0,73,0,110,
586916,0,642,1,137, 71200,116,0,86,0,
58701771,16,0,187,1, 7121101,0,99,0,86,
58711901,1772,16,0,187, 71220,101,0,99,0,
58721,2658,1773,16,0, 712365,0,114,0,103,
5873187,1,1153,1774,16, 71240,69,0,118,0,
58740,187,1,151,1775, 7125101,0,110,0,116,
587516,0,187,1,1407, 71260,1,-1,1,5,
58761776,16,0,187,1, 71272086,20,2087,4,38,
58771659,1777,16,0,187, 712873,0,110,0,116,
58781,2413,1778,16,0, 71290,86,0,101,0,
5879187,1,406,1779,16, 713099,0,86,0,101,
58800,187,1,1371,1780, 71310,99,0,65,0,
588116,0,187,1,2105, 7132114,0,103,0,69,
5882814,1,166,1781,16,
58830,187,1,525,1782,
588416,0,187,1,1622,
58851783,16,0,187,1,
58861931,861,1,1932,1784,
588716,0,456,1,1933,
58881785,16,0,187,1,
5889431,1786,16,0,187,
58901,1585,1787,16,0,
5891187,1,182,1788,16,
58920,187,1,1189,1789,
589316,0,187,1,1443,
58941790,16,0,187,1,
58951695,1791,16,0,187,
58961,2198,1792,16,0,
5897187,1,447,1793,16,
58980,187,1,199,1794,
589916,0,187,1,2459,
5900882,1,1958,1795,16,
59010,187,1,2462,889,
59021,1657,894,1,2464,
5903899,1,459,1796,16,
59040,187,1,462,1797,
590516,0,187,1,2471,
59061798,17,1799,15,1717,
59071,-1,1,5,1800,
590820,1801,4,16,69,
59090,118,0,101,0, 71330,118,0,101,0,
5910110,0,116,0,95, 7134110,0,116,0,95,
59110,51,0,52,0, 71350,49,0,1,375,
59121,321,1,3,1,
59132,1,1,1802,22,
59141,182,1,2472,1803,
591517,1804,15,1717,1,
5916-1,1,5,1805,20,
59171806,4,16,69,0,
5918118,0,101,0,110,
59190,116,0,95,0,
592051,0,51,0,1,
5921320,1,3,1,2,
59221,1,1807,22,1,
5923181,1,2473,1808,17,
59241809,15,1717,1,-1,
59251,5,1810,20,1811,
59264,16,69,0,118,
59270,101,0,110,0,
5928116,0,95,0,51,
59290,50,0,1,319,
59301,3,1,2,1, 71361,3,1,2,1,
59311,1812,22,1,180, 71371,2088,22,1,212,
59321,2474,1813,17,1814, 71381,2473,2089,17,2090,
593315,1717,1,-1,1, 713915,2091,4,36,37,
59345,1815,20,1816,4, 71400,73,0,110,0,
593516,69,0,118,0, 7141116,0,82,0,111,
5936101,0,110,0,116, 71420,116,0,82,0,
59370,95,0,51,0, 7143111,0,116,0,65,
593849,0,1,318,1, 71440,114,0,103,0,
59393,1,2,1,1,
59401817,22,1,179,1,
59412475,1818,17,1819,15,
59421717,1,-1,1,5,
59431820,20,1821,4,16,
594469,0,118,0,101, 714569,0,118,0,101,
59450,110,0,116,0, 71460,110,0,116,0,
594695,0,51,0,48, 71471,-1,1,5,2092,
59470,1,317,1,3, 714820,2093,4,38,73,
59481,2,1,1,1822, 71490,110,0,116,0,
594922,1,178,1,2476, 715082,0,111,0,116,
59501823,17,1824,15,1717, 71510,82,0,111,0,
59511,-1,1,5,1825, 7152116,0,65,0,114,
595220,1826,4,16,69, 71530,103,0,69,0,
59530,118,0,101,0,
5954110,0,116,0,95,
59550,50,0,57,0,
59561,316,1,3,1,
59572,1,1,1827,22,
59581,177,1,2477,1828,
595917,1829,15,1717,1,
5960-1,1,5,1830,20,
59611831,4,16,69,0,
5962118,0,101,0,110, 7154118,0,101,0,110,
59630,116,0,95,0, 71550,116,0,95,0,
596450,0,56,0,1, 715649,0,1,374,1,
5965315,1,3,1,2, 71573,1,2,1,1,
59661,1,1832,22,1, 71582094,22,1,211,1,
5967176,1,2227,908,1, 71592474,2095,17,2096,15,
59682479,1833,17,1834,15, 71602097,4,30,37,0,
59691717,1,-1,1,5, 716186,0,101,0,99,
59701835,20,1836,4,16, 71620,116,0,111,0,
7163114,0,65,0,114,
71640,103,0,69,0,
7165118,0,101,0,110,
71660,116,0,1,-1,
71671,5,2098,20,2099,
71684,32,86,0,101,
71690,99,0,116,0,
7170111,0,114,0,65,
71710,114,0,103,0,
597169,0,118,0,101, 717269,0,118,0,101,
59720,110,0,116,0, 71730,110,0,116,0,
597395,0,50,0,54, 717495,0,51,0,1,
59740,1,313,1,3, 7175373,1,3,1,2,
59751,2,1,1,1837, 71761,1,2100,22,1,
597622,1,174,1,1225, 7177210,1,2475,2101,17,
59771838,16,0,187,1, 71782102,15,2097,1,-1,
59782481,1839,17,1840,15, 71791,5,2103,20,2104,
59791717,1,-1,1,5, 71804,32,86,0,101,
59801841,20,1842,4,16, 71810,99,0,116,0,
7182111,0,114,0,65,
71830,114,0,103,0,
598169,0,118,0,101, 718469,0,118,0,101,
59820,110,0,116,0, 71850,110,0,116,0,
598395,0,50,0,52, 718695,0,50,0,1,
59840,1,311,1,3, 7187372,1,3,1,2,
59851,2,1,1,1843, 71881,1,2105,22,1,
598622,1,172,1,2482, 7189209,1,2476,2106,17,
59871844,17,1845,15,1717, 71902107,15,2097,1,-1,
59881,-1,1,5,1846, 71911,5,2108,20,2109,
598920,1847,4,16,69, 71924,32,86,0,101,
71930,99,0,116,0,
7194111,0,114,0,65,
71950,114,0,103,0,
719669,0,118,0,101,
71970,110,0,116,0,
719895,0,49,0,1,
7199371,1,3,1,2,
72001,1,2110,22,1,
7201208,1,2477,2111,17,
72022112,15,1990,1,-1,
72031,5,2113,20,2114,
72044,28,73,0,110,
72050,116,0,65,0,
7206114,0,103,0,69,
59900,118,0,101,0, 72070,118,0,101,0,
5991110,0,116,0,95, 7208110,0,116,0,95,
59920,50,0,51,0, 72090,49,0,48,0,
59931,310,1,3,1, 72101,370,1,3,1,
59942,1,1,1848,22, 72112,1,1,2115,22,
59951,171,1,2483,1849, 72121,207,1,2227,1030,
599617,1850,15,1717,1, 72131,2479,2116,17,2117,
5997-1,1,5,1851,20, 721415,1990,1,-1,1,
59981852,4,16,69,0, 72155,2118,20,2119,4,
721626,73,0,110,0,
7217116,0,65,0,114,
72180,103,0,69,0,
5999118,0,101,0,110, 7219118,0,101,0,110,
60000,116,0,95,0, 72200,116,0,95,0,
600150,0,50,0,1, 722156,0,1,368,1,
6002309,1,3,1,2, 72223,1,2,1,1,
60031,1,1853,22,1, 72232120,22,1,205,1,
6004170,1,1731,1854,16, 72241225,2121,16,0,206,
60050,187,1,2485,1855, 72251,2481,2122,17,2123,
600617,1856,15,1717,1, 722615,1990,1,-1,1,
6007-1,1,5,1857,20, 72275,2124,20,2125,4,
60081858,4,16,69,0, 722826,73,0,110,0,
7229116,0,65,0,114,
72300,103,0,69,0,
6009118,0,101,0,110, 7231118,0,101,0,110,
60100,116,0,95,0, 72320,116,0,95,0,
601150,0,48,0,1, 723354,0,1,366,1,
6012307,1,3,1,2, 72343,1,2,1,1,
60131,1,1859,22,1, 72352126,22,1,203,1,
6014168,1,2486,1860,17, 72362482,2127,17,2128,15,
60151861,15,1717,1,-1, 72371990,1,-1,1,5,
60161,5,1862,20,1863, 72382129,20,2130,4,26,
60174,16,69,0,118, 723973,0,110,0,116,
72400,65,0,114,0,
7241103,0,69,0,118,
60180,101,0,110,0, 72420,101,0,110,0,
6019116,0,95,0,49, 7243116,0,95,0,53,
60200,57,0,1,306, 72440,1,365,1,3,
60211,3,1,2,1, 72451,2,1,1,2131,
60221,1864,22,1,167, 724622,1,202,1,2483,
60231,2487,1865,17,1866, 72472132,17,2133,15,1990,
602415,1717,1,-1,1, 72481,-1,1,5,2134,
60255,1867,20,1868,4, 724920,2135,4,26,73,
602616,69,0,118,0, 72500,110,0,116,0,
725165,0,114,0,103,
72520,69,0,118,0,
6027101,0,110,0,116, 7253101,0,110,0,116,
60280,95,0,49,0, 72540,95,0,52,0,
602956,0,1,305,1, 72551,364,1,3,1,
60303,1,2,1,1, 72562,1,1,2136,22,
60311869,22,1,166,1, 72571,201,1,1731,2137,
60322488,1870,17,1871,15, 725816,0,206,1,2485,
60331717,1,-1,1,5, 72592138,17,2139,15,1990,
60341872,20,1873,4,16, 72601,-1,1,5,2140,
726120,2141,4,26,73,
72620,110,0,116,0,
726365,0,114,0,103,
72640,69,0,118,0,
7265101,0,110,0,116,
72660,95,0,50,0,
72671,362,1,3,1,
72682,1,1,2142,22,
72691,199,1,2486,2143,
727017,2144,15,1990,1,
7271-1,1,5,2145,20,
72722146,4,26,73,0,
7273110,0,116,0,65,
72740,114,0,103,0,
603569,0,118,0,101, 727569,0,118,0,101,
60360,110,0,116,0, 72760,110,0,116,0,
603795,0,49,0,55, 727795,0,49,0,1,
60380,1,304,1,3, 7278361,1,3,1,2,
60391,2,1,1,1874, 72791,1,2147,22,1,
604022,1,165,1,2489, 7280198,1,2487,2148,17,
60411875,17,1876,15,1717, 72812149,15,2150,4,24,
60421,-1,1,5,1877, 728237,0,75,0,101,
604320,1878,4,16,69, 72830,121,0,65,0,
7284114,0,103,0,69,
72850,118,0,101,0,
7286110,0,116,0,1,
7287-1,1,5,2151,20,
72882152,4,26,75,0,
7289101,0,121,0,65,
72900,114,0,103,0,
729169,0,118,0,101,
72920,110,0,116,0,
729395,0,50,0,1,
7294360,1,3,1,2,
72951,1,2153,22,1,
7296197,1,2488,2154,17,
72972155,15,2150,1,-1,
72981,5,2156,20,2157,
72994,26,75,0,101,
73000,121,0,65,0,
7301114,0,103,0,69,
60440,118,0,101,0, 73020,118,0,101,0,
6045110,0,116,0,95, 7303110,0,116,0,95,
60460,49,0,54,0, 73040,49,0,1,359,
60471,303,1,3,1, 73051,3,1,2,1,
60482,1,1,1879,22, 73061,2158,22,1,196,
60491,164,1,2490,1880, 73071,2489,2159,17,2160,
605017,1881,15,1717,1, 730815,2005,1,-1,1,
6051-1,1,5,1882,20, 73095,2161,20,2162,4,
60521883,4,16,69,0, 731028,86,0,111,0,
6053118,0,101,0,110, 7311105,0,100,0,65,
60540,116,0,95,0, 73120,114,0,103,0,
605549,0,53,0,1,
6056302,1,3,1,2,
60571,1,1884,22,1,
6058163,1,1989,916,1,
60592492,1885,17,1886,15,
60601717,1,-1,1,5,
60611887,20,1888,4,16,
606269,0,118,0,101, 731369,0,118,0,101,
60630,110,0,116,0, 73140,110,0,116,0,
606495,0,49,0,51, 731595,0,56,0,1,
60650,1,300,1,3, 7316358,1,3,1,2,
60661,2,1,1,1889, 73171,1,2163,22,1,
606722,1,161,1,2493, 7318195,1,2490,2164,17,
60681890,17,1891,15,1717, 73192165,15,2005,1,-1,
60691,-1,1,5,1892, 73201,5,2166,20,2167,
607020,1893,4,16,69, 73214,28,86,0,111,
73220,105,0,100,0,
732365,0,114,0,103,
73240,69,0,118,0,
7325101,0,110,0,116,
73260,95,0,55,0,
73271,357,1,3,1,
73282,1,1,2168,22,
73291,194,1,1989,1038,
73301,2492,2169,17,2170,
733115,2005,1,-1,1,
73325,2171,20,2172,4,
733328,86,0,111,0,
7334105,0,100,0,65,
73350,114,0,103,0,
733669,0,118,0,101,
73370,110,0,116,0,
733895,0,53,0,1,
7339355,1,3,1,2,
73401,1,2173,22,1,
7341192,1,2493,2174,17,
73422175,15,2005,1,-1,
73431,5,2176,20,2177,
73444,28,86,0,111,
73450,105,0,100,0,
734665,0,114,0,103,
73470,69,0,118,0,
7348101,0,110,0,116,
73490,95,0,52,0,
73501,354,1,3,1,
73512,1,1,2178,22,
73521,191,1,2494,2179,
735317,2180,15,2005,1,
7354-1,1,5,2181,20,
73552182,4,28,86,0,
7356111,0,105,0,100,
73570,65,0,114,0,
7358103,0,69,0,118,
73590,101,0,110,0,
7360116,0,95,0,51,
73610,1,353,1,3,
73621,2,1,1,2183,
736322,1,190,1,236,
73642184,16,0,206,1,
73652496,2185,17,2186,15,
73662005,1,-1,1,5,
73672187,20,2188,4,28,
736886,0,111,0,105,
73690,100,0,65,0,
7370114,0,103,0,69,
60710,118,0,101,0, 73710,118,0,101,0,
6072110,0,116,0,95, 7372110,0,116,0,95,
60730,49,0,50,0, 73730,49,0,1,351,
60741,299,1,3,1, 73741,3,1,2,1,
60752,1,1,1894,22, 73751,2189,22,1,188,
60761,160,1,2494,1895, 73761,2497,2190,17,2191,
607717,1896,15,1717,1, 737715,2192,4,12,37,
6078-1,1,5,1897,20, 73780,69,0,118,0,
60791898,4,16,69,0, 7379101,0,110,0,116,
6080118,0,101,0,110, 73800,1,-1,1,5,
60810,116,0,95,0, 73812193,20,2194,4,14,
608249,0,49,0,1,
6083298,1,3,1,2,
60841,1,1899,22,1,
6085159,1,236,1900,16,
60860,187,1,2496,1901,
608717,1902,15,1717,1,
6088-1,1,5,1903,20,
60891904,4,14,69,0,
6090118,0,101,0,110,
60910,116,0,95,0,
609257,0,1,296,1,
60933,1,2,1,1,
60941905,22,1,157,1,
60952497,1906,17,1907,15,
60961717,1,-1,1,5,
60971908,20,1909,4,14,
609869,0,118,0,101, 738269,0,118,0,101,
60990,110,0,116,0, 73830,110,0,116,0,
610095,0,56,0,1, 738495,0,56,0,1,
6101295,1,3,1,2, 7385350,1,3,1,2,
61021,1,1910,22,1, 73861,1,2195,22,1,
6103156,1,2498,1911,17, 7387187,1,2498,2196,17,
61041912,15,1717,1,-1, 73882197,15,2192,1,-1,
61051,5,1913,20,1914, 73891,5,2198,20,2199,
61064,14,69,0,118, 73904,14,69,0,118,
61070,101,0,110,0, 73910,101,0,110,0,
6108116,0,95,0,55, 7392116,0,95,0,55,
61090,1,294,1,3, 73930,1,349,1,3,
61101,2,1,1,1915, 73941,2,1,1,2200,
611122,1,155,1,2499, 739522,1,186,1,2499,
61121916,17,1917,15,1717, 73962201,17,2202,15,2192,
61131,-1,1,5,1918, 73971,-1,1,5,2203,
611420,1919,4,14,69, 739820,2204,4,14,69,
61150,118,0,101,0, 73990,118,0,101,0,
6116110,0,116,0,95, 7400110,0,116,0,95,
61170,54,0,1,293, 74010,54,0,1,348,
61181,3,1,2,1, 74021,3,1,2,1,
61191,1920,22,1,154, 74031,2205,22,1,185,
61201,2500,1921,17,1922, 74041,2500,2206,17,2207,
612115,1717,1,-1,1, 740515,2192,1,-1,1,
61225,1923,20,1924,4, 74065,2208,20,2209,4,
612314,69,0,118,0, 740714,69,0,118,0,
6124101,0,110,0,116, 7408101,0,110,0,116,
61250,95,0,53,0, 74090,95,0,53,0,
61261,292,1,3,1, 74101,347,1,3,1,
61272,1,1,1925,22, 74112,1,1,2210,22,
61281,153,1,2501,1926, 74121,184,1,2501,2211,
612917,1927,15,1717,1, 741317,2212,15,2192,1,
6130-1,1,5,1928,20, 7414-1,1,5,2213,20,
61311929,4,14,69,0, 74152214,4,14,69,0,
6132118,0,101,0,110, 7416118,0,101,0,110,
61330,116,0,95,0, 74170,116,0,95,0,
613452,0,1,291,1, 741852,0,1,346,1,
61353,1,2,1,1, 74193,1,2,1,1,
61361930,22,1,152,1, 74202215,22,1,183,1,
61372502,1931,17,1932,15, 74212502,2216,17,2217,15,
61381717,1,-1,1,5, 74222192,1,-1,1,5,
61391933,20,1934,4,14, 74232218,20,2219,4,14,
614069,0,118,0,101, 742469,0,118,0,101,
61410,110,0,116,0, 74250,110,0,116,0,
614295,0,51,0,1, 742695,0,51,0,1,
6143290,1,3,1,2, 7427345,1,3,1,2,
61441,1,1935,22,1, 74281,1,2220,22,1,
6145151,1,2503,1936,17, 7429182,1,2503,2221,17,
61461937,15,1717,1,-1, 74302222,15,2192,1,-1,
61471,5,1938,20,1939, 74311,5,2223,20,2224,
61484,14,69,0,118, 74324,14,69,0,118,
61490,101,0,110,0, 74330,101,0,110,0,
6150116,0,95,0,50, 7434116,0,95,0,50,
61510,1,289,1,3, 74350,1,344,1,3,
61521,2,1,1,1940, 74361,2,1,1,2225,
615322,1,150,1,2504, 743722,1,181,1,2504,
61541941,17,1942,15,1717, 74382226,17,2227,15,2192,
61551,-1,1,5,1943, 74391,-1,1,5,2228,
615620,1944,4,14,69, 744020,2229,4,14,69,
61570,118,0,101,0, 74410,118,0,101,0,
6158110,0,116,0,95, 7442110,0,116,0,95,
61590,49,0,1,288, 74430,49,0,1,343,
61601,3,1,2,1, 74441,3,1,2,1,
61611,1945,22,1,149, 74451,2230,22,1,180,
61621,2505,1946,16,0, 74461,2505,2231,16,0,
6163433,1,217,1947,16, 7447469,1,217,2232,16,
61640,187,1,1756,1948, 74480,206,1,1756,2233,
616516,0,187,1,17, 744916,0,206,1,17,
61661949,19,154,1,17, 74502234,19,163,1,17,
61671950,5,117,1,1, 74512235,5,134,1,1,
61681951,17,1952,15,1953, 74522236,17,2237,15,2238,
61694,18,37,0,84, 74534,18,37,0,84,
61700,121,0,112,0, 74540,121,0,112,0,
6171101,0,110,0,97, 7455101,0,110,0,97,
61720,109,0,101,0, 74560,109,0,101,0,
61731,-1,1,5,1954, 74571,-1,1,5,2239,
617420,1955,4,20,84, 745820,2240,4,20,84,
61750,121,0,112,0, 74590,121,0,112,0,
6176101,0,110,0,97, 7460101,0,110,0,97,
61770,109,0,101,0, 74610,109,0,101,0,
617895,0,55,0,1, 746295,0,55,0,1,
6179287,1,3,1,2, 7463342,1,3,1,2,
61801,1,1956,22,1, 74641,1,2241,22,1,
6181148,1,2,1957,17, 7465179,1,2,2242,17,
61821958,15,1953,1,-1, 74662243,15,2238,1,-1,
61831,5,1959,20,1960, 74671,5,2244,20,2245,
61844,20,84,0,121, 74684,20,84,0,121,
61850,112,0,101,0, 74690,112,0,101,0,
6186110,0,97,0,109, 7470110,0,97,0,109,
61870,101,0,95,0, 74710,101,0,95,0,
618854,0,1,286,1, 747254,0,1,341,1,
61893,1,2,1,1, 74733,1,2,1,1,
61901961,22,1,147,1, 74742246,22,1,178,1,
61913,1962,17,1963,15, 74753,2247,17,2248,15,
61921953,1,-1,1,5, 74762238,1,-1,1,5,
61931964,20,1965,4,20, 74772249,20,2250,4,20,
619484,0,121,0,112, 747884,0,121,0,112,
61950,101,0,110,0, 74790,101,0,110,0,
619697,0,109,0,101, 748097,0,109,0,101,
61970,95,0,53,0, 74810,95,0,53,0,
61981,285,1,3,1, 74821,340,1,3,1,
61992,1,1,1966,22, 74832,1,1,2251,22,
62001,146,1,4,1967, 74841,177,1,4,2252,
620117,1968,15,1953,1, 748517,2253,15,2238,1,
6202-1,1,5,1969,20, 7486-1,1,5,2254,20,
62031970,4,20,84,0, 74872255,4,20,84,0,
6204121,0,112,0,101, 7488121,0,112,0,101,
62050,110,0,97,0, 74890,110,0,97,0,
6206109,0,101,0,95, 7490109,0,101,0,95,
62070,52,0,1,284, 74910,52,0,1,339,
62081,3,1,2,1, 74921,3,1,2,1,
62091,1971,22,1,145, 74931,2256,22,1,176,
62101,5,1972,17,1973, 74941,5,2257,17,2258,
621115,1953,1,-1,1, 749515,2238,1,-1,1,
62125,1974,20,1975,4, 74965,2259,20,2260,4,
621320,84,0,121,0, 749720,84,0,121,0,
6214112,0,101,0,110, 7498112,0,101,0,110,
62150,97,0,109,0, 74990,97,0,109,0,
6216101,0,95,0,51, 7500101,0,95,0,51,
62170,1,283,1,3, 75010,1,338,1,3,
62181,2,1,1,1976, 75021,2,1,1,2261,
621922,1,144,1,6, 750322,1,175,1,6,
62201977,17,1978,15,1953, 75042262,17,2263,15,2238,
62211,-1,1,5,1979, 75051,-1,1,5,2264,
622220,1980,4,20,84, 750620,2265,4,20,84,
62230,121,0,112,0, 75070,121,0,112,0,
6224101,0,110,0,97, 7508101,0,110,0,97,
62250,109,0,101,0, 75090,109,0,101,0,
622695,0,50,0,1, 751095,0,50,0,1,
6227282,1,3,1,2, 7511337,1,3,1,2,
62281,1,1981,22,1, 75121,1,2266,22,1,
6229143,1,7,1982,17, 7513174,1,7,2267,17,
62301983,15,1953,1,-1, 75142268,15,2238,1,-1,
62311,5,1984,20,1985, 75151,5,2269,20,2270,
62324,20,84,0,121, 75164,20,84,0,121,
62330,112,0,101,0, 75170,112,0,101,0,
6234110,0,97,0,109, 7518110,0,97,0,109,
62350,101,0,95,0, 75190,101,0,95,0,
623649,0,1,281,1, 752049,0,1,336,1,
62373,1,2,1,1, 75213,1,2,1,1,
62381986,22,1,142,1, 75222271,22,1,173,1,
62391514,1108,1,9,1113, 75231514,1230,1,9,1235,
62401,10,1642,1,262, 75241,10,1889,1,262,
62411119,1,1267,1125,1, 75251241,1,1267,1247,1,
6242481,1646,1,1521,1130, 75262775,2272,16,0,792,
62431,1773,1987,16,0, 75271,1521,1252,1,1773,
6244234,1,19,1147,1, 75282273,16,0,264,1,
624520,1988,16,0,152, 75292527,1895,1,19,1269,
62461,2281,1154,1,525, 75301,20,2274,16,0,
62471216,1,30,1654,1, 7531161,1,2531,2275,17,
6248283,1172,1,1010,1989, 75322276,15,2277,4,66,
624916,0,593,1,40, 753337,0,73,0,110,
62501177,1,41,1659,1, 75340,116,0,86,0,
625142,1662,1,44,1183, 7535101,0,99,0,86,
62521,1260,1096,1,47, 75360,101,0,99,0,
62531184,1,1303,1307,1, 753765,0,114,0,103,
625449,1196,1,50,1201, 75380,117,0,109,0,
62551,48,1190,1,305, 7539101,0,110,0,116,
62561211,1,51,1206,1,
625761,1990,16,0,194,
62581,63,1222,1,66,
62591228,1,67,1233,1,
62601478,1458,1,69,1243,
62611,70,1248,1,68,
62621238,1,73,1991,16,
62630,204,1,74,1253,
62641,1013,1258,1,2335,
62651992,16,0,239,1,
6266328,1302,1,1048,1344,
62671,82,1280,1,1840,
62681993,16,0,303,1,
62692515,1994,16,0,436,
62701,1341,1297,1,1094,
62711995,16,0,666,1,
62721096,1312,1,93,1318,
62731,1550,1323,1,352,
62741349,1,1011,1102,1,
6275107,1338,1,1114,1343,
62761,1871,1996,16,0,
6277313,1,1370,1453,1,
6278118,1355,1,1123,1360,
62791,1332,1263,1,1377,
62801371,1,375,1376,1,
62811882,1997,16,0,327,
62821,377,1381,1,827,
62831331,1,380,1391,1,
6284130,1414,1,2074,1998,
628516,0,554,1,371,
62861365,1,373,1409,1,
62871012,1999,16,0,595,
62881,379,1386,1,143,
62891419,1,1152,1426,1,
62901406,1431,1,1159,1438,
62911,157,1443,1,1413,
62921448,1,883,1397,1,
62931296,1167,1,172,1469,
62941,1665,1474,1,1939,
62952000,16,0,435,1,
62961188,1479,1,1442,1484,
62971,188,1518,1,942,
62981490,1,1195,1496,1,
62991449,1501,1,1701,1506,
63001,447,1511,1,205,
63011523,1,2467,1677,1,
6302464,1683,1,2642,1669,
63031,2197,2001,16,0,
6304662,1,1224,1528,1,
6305223,1533,1,1730,1538,
63061,2651,2002,16,0,
6307570,1,477,1549,1,
63081231,1554,1,479,1559,
63091,480,1564,1,1485,
63101570,1,459,1688,1,
6311476,1543,1,242,1578,
63121,478,1583,1,2506,
63131690,1,1001,1588,1,
63141002,1593,1,18,2003,
631519,490,1,18,2004,
63165,84,1,1011,1102,
63171,1012,2005,16,0,
6318488,1,1013,1258,1,
6319262,1119,1,1267,2006,
632016,0,488,1,515,
63212007,16,0,488,1,
63221521,2008,16,0,488,
63231,525,1216,1,283,
63241172,1,2299,2009,16,
63250,488,1,42,2010,
632616,0,488,1,40,
63271177,1,44,1183,1,
632847,1184,1,1303,2011,
632916,0,488,1,1555,
63302012,16,0,488,1,
633150,1201,1,48,1190,
63321,49,1196,1,51,
63331206,1,63,1222,1,
6334305,1211,1,66,1228,
63351,67,1233,1,68,
63361238,1,69,1243,1,
633770,1248,1,73,2013,
633816,0,488,1,74,
63391253,1,328,1302,1,
63401048,2014,16,0,488,
63411,82,2015,16,0,
6342488,1,1840,2016,16,
63430,488,1,1591,2017,
634416,0,488,1,1341,
63452018,16,0,488,1,
63461096,1312,1,93,1318,
63471,352,1349,1,107,
63482019,16,0,488,1,
63491114,1343,1,118,2020,
635016,0,488,1,1123,
63512021,16,0,488,1,
6352371,1365,1,1628,2022,
635316,0,488,1,375,
63541376,1,1882,2023,16,
63550,488,1,377,1381,
63561,379,1386,1,380,
63571391,1,883,2024,16,
63580,488,1,373,1409,
63591,130,2025,16,0,
6360488,1,143,2026,16,
63610,488,1,387,2027,
636216,0,488,1,2664,
63632028,16,0,488,1,
63641159,2029,16,0,488,
63651,157,2030,16,0,
6366488,1,1413,2031,16,
63670,488,1,1665,2032,
636816,0,488,1,412,
63692033,16,0,488,1,
63701377,2034,16,0,488,
63711,172,2035,16,0,
6372488,1,1939,2036,16,
63730,488,1,437,2037,
637416,0,488,1,188,
63752038,16,0,488,1,
6376942,2039,16,0,488,
63771,1195,2040,16,0,
6378488,1,1449,2041,16,
63790,488,1,1701,2042,
638016,0,488,1,447,
63811511,1,205,2043,16,
63820,488,1,827,2044,
638316,0,488,1,223,
63842045,16,0,488,1,
6385476,1543,1,477,1549,
63861,1231,2046,16,0,
6387488,1,479,1559,1,
6388480,1564,1,1485,2047,
638916,0,488,1,1737,
63902048,16,0,488,1,
6391242,2049,16,0,488,
63921,478,1583,1,1001,
63931588,1,1002,1593,1,
639419,2050,19,225,1,
639519,2051,5,176,1,
6396256,2052,16,0,223,
63971,1261,2053,16,0,
6398223,1,1011,1102,1,
63991012,2054,16,0,455,
64001,2458,876,1,262,
64011119,1,1267,2055,16,
64020,455,1,2021,718,
64031,1521,2056,16,0,
6404455,1,1775,2057,16,
64050,223,1,2029,725,
64061,2030,731,1,2031,
6407736,1,2032,741,1,
64082033,746,1,277,2058,
640916,0,223,1,2035,
6410752,1,2037,757,1,
64112039,762,1,32,2059,
641216,0,223,1,2464,
6413899,1,2293,2060,16,
64140,223,1,2043,774,
64151,2045,779,1,2299,
64162061,16,0,455,1,
641741,2062,16,0,223,
64181,42,2063,16,0,
6419455,1,40,1177,1,
642044,1183,1,43,2064,
642116,0,223,1,1804,
64222065,16,0,223,1,
642348,1190,1,49,1196,
64241,47,1184,1,51,
64251206,1,52,2066,16,
64260,223,1,50,1201,
64271,305,1211,1,1096,
64281312,1,1515,2067,16,
64290,223,1,2318,2068,
643016,0,223,1,283,
64311172,1,63,1222,1,
643266,1228,1,67,1233,
64331,68,1238,1,69,
64341243,1,70,1248,1,
643571,2069,16,0,223,
64361,73,2070,16,0,
6437455,1,74,1253,1,
64381013,1258,1,76,2071,
643916,0,223,1,1834,
64402072,16,0,223,1,
64412337,2073,16,0,223,
64421,79,2074,16,0,
6443223,1,1335,2075,16,
64440,223,1,299,2076,
644516,0,223,1,82,
64462077,16,0,455,1,
64471840,2078,16,0,455,
64481,1297,2079,16,0,
6449223,1,85,2080,16,
64500,223,1,1341,2081,
645116,0,455,1,89,
64522082,16,0,223,1,
64531303,2083,16,0,455,
64541,509,2084,16,0,
6455223,1,93,1318,1,
6456322,2085,16,0,223,
64571,97,2086,16,0,
6458223,1,2041,768,1,
64591555,2087,16,0,455,
64601,827,2088,16,0,
6461455,1,102,2089,16,
64620,223,1,1860,821,
64631,1803,787,1,2364,
6464827,1,107,2090,16,
64650,455,1,1114,1343,
64661,112,2091,16,0,
6467223,1,1117,2092,16,
64680,223,1,352,1349,
64691,1873,835,1,118,
64702093,16,0,455,1,
64711123,2094,16,0,455,
64721,371,1365,1,515,
64732095,16,0,455,1,
64741377,2096,16,0,455,
64751,124,2097,16,0,
6476223,1,1882,2098,16,
64770,455,1,377,1381,
64781,379,1386,1,380,
64791391,1,130,2099,16,
64800,455,1,346,2100,
648116,0,223,1,2075,
64822101,16,0,223,1,
6483373,1409,1,387,2102,
648416,0,455,1,137,
64852103,16,0,223,1,
6486143,2104,16,0,455,
64871,1901,2105,16,0,
6488223,1,1048,2106,16,
64890,455,1,2658,2107,
649016,0,223,1,1153,
64912108,16,0,223,1,
6492375,1376,1,151,2109,
649316,0,223,1,1407,
64942110,16,0,223,1,
64951659,2111,16,0,223,
64961,2413,2112,16,0,
6497223,1,1159,2113,16,
64980,455,1,381,2114,
649916,0,223,1,157,
65002115,16,0,455,1,
65011413,2116,16,0,455,
65021,883,2117,16,0,
6503455,1,1371,2118,16,
65040,223,1,328,1302,
65051,2105,814,1,2106,
65062119,16,0,223,1,
6507166,2120,16,0,223,
65081,525,2121,16,0,
6509223,1,1622,2122,16,
65100,223,1,406,2123,
651116,0,223,1,1574,
6512799,1,172,2124,16,
65130,455,1,1931,861,
65141,412,2125,16,0,
6515455,1,1933,2126,16,
65160,223,1,1876,2127,
651716,0,223,1,431,
65182128,16,0,223,1,
65191585,2129,16,0,223,
65201,182,2130,16,0,
6521223,1,1628,2131,16,
65220,455,1,1189,2132,
652316,0,223,1,437,
65242133,16,0,455,1,
65251591,2134,16,0,455,
65261,188,2135,16,0,
6527455,1,1695,2136,16,
65280,223,1,2198,2137,
652916,0,223,1,1195,
65302138,16,0,455,1,
65311449,2139,16,0,455,
65321,1701,2140,16,0,
6533455,1,447,2141,16,
65340,223,1,199,2142,
653516,0,223,1,2459,
6536882,1,1958,2143,16,
65370,223,1,2462,889,
65381,1657,894,1,205,
65392144,16,0,455,1,
6540459,2145,16,0,223,
65411,462,2146,16,0,
6542223,1,1665,2147,16,
65430,455,1,217,2148,
654416,0,223,1,2227,
6545908,1,942,2149,16,
65460,455,1,1225,2150,
654716,0,223,1,223,
65482151,16,0,455,1,
65491479,2152,16,0,223,
65501,1731,2153,16,0,
6551223,1,477,1549,1,
65521231,2154,16,0,455,
65531,479,1559,1,480,
65541564,1,1485,2155,16,
65550,455,1,1737,2156,
655616,0,455,1,1989,
6557916,1,1990,2157,16,
65580,223,1,1443,2158,
655916,0,223,1,236,
65602159,16,0,223,1,
65612136,842,1,2664,2160,
656216,0,455,1,476,
65631543,1,242,2161,16,
65640,455,1,478,1583,
65651,1939,2162,16,0,
6566455,1,1001,1588,1,
65671002,1593,1,1756,2163,
656816,0,223,1,20,
65692164,19,442,1,20,
65702165,5,84,1,1011,
65711102,1,1012,2166,16,
65720,440,1,1013,1258,
65731,262,1119,1,1267,
65742167,16,0,440,1,
6575515,2168,16,0,440,
65761,1521,2169,16,0,
6577440,1,525,1216,1,
6578283,1172,1,2299,2170,
657916,0,440,1,42,
65802171,16,0,440,1,
658140,1177,1,44,1183,
65821,47,1184,1,1303,
65832172,16,0,440,1,
65841555,2173,16,0,440,
65851,50,1201,1,48,
65861190,1,49,1196,1,
658751,1206,1,63,1222,
65881,305,1211,1,66,
65891228,1,67,1233,1,
659068,1238,1,69,1243,
65911,70,1248,1,73,
65922174,16,0,440,1,
659374,1253,1,328,2175,
659416,0,440,1,1048,
65952176,16,0,440,1,
659682,2177,16,0,440,
65971,1840,2178,16,0,
6598440,1,1591,2179,16,
65990,440,1,1341,2180,
660016,0,440,1,1096,
66011312,1,93,1318,1,
6602352,2181,16,0,440,
66031,107,2182,16,0,
6604440,1,1114,1343,1,
6605118,2183,16,0,440,
66061,1123,2184,16,0,
6607440,1,371,1365,1,
66081628,2185,16,0,440,
66091,375,1376,1,1882,
66102186,16,0,440,1,
6611377,1381,1,379,1386,
66121,380,1391,1,883,
66132187,16,0,440,1,
6614373,1409,1,130,2188,
661516,0,440,1,143,
66162189,16,0,440,1,
6617387,2190,16,0,440,
66181,2664,2191,16,0,
6619440,1,1159,2192,16,
66200,440,1,157,2193,
662116,0,440,1,1413,
66222194,16,0,440,1,
66231665,2195,16,0,440,
66241,412,2196,16,0,
6625440,1,1377,2197,16,
66260,440,1,172,2198,
662716,0,440,1,1939,
66282199,16,0,440,1,
6629437,2200,16,0,440,
66301,188,2201,16,0,
6631440,1,942,2202,16,
66320,440,1,1195,2203,
663316,0,440,1,1449,
66342204,16,0,440,1,
66351701,2205,16,0,440,
66361,447,1511,1,205,
66372206,16,0,440,1,
6638827,2207,16,0,440,
66391,223,2208,16,0,
6640440,1,476,1543,1,
6641477,1549,1,1231,2209,
664216,0,440,1,479,
66431559,1,480,1564,1,
66441485,2210,16,0,440,
66451,1737,2211,16,0,
6646440,1,242,2212,16,
66470,440,1,478,1583,
66481,1001,1588,1,1002,
66491593,1,21,2213,19,
6650432,1,21,2214,5,
665184,1,1011,1102,1,
66521012,2215,16,0,430,
66531,1013,1258,1,262,
66541119,1,1267,2216,16,
66550,430,1,515,2217,
665616,0,430,1,1521,
66572218,16,0,430,1,
6658525,1216,1,283,1172,
66591,2299,2219,16,0,
6660430,1,42,2220,16,
66610,430,1,40,1177,
66621,44,1183,1,47,
66631184,1,1303,2221,16,
66640,430,1,1555,2222,
666516,0,430,1,50,
66661201,1,48,1190,1,
666749,1196,1,51,1206,
66681,63,1222,1,305,
66691211,1,66,1228,1,
667067,1233,1,68,1238,
66711,69,1243,1,70,
66721248,1,73,2223,16,
66730,430,1,74,1253,
66741,328,2224,16,0,
6675430,1,1048,2225,16,
66760,430,1,82,2226,
667716,0,430,1,1840,
66782227,16,0,430,1,
66791591,2228,16,0,430,
66801,1341,2229,16,0,
6681430,1,1096,1312,1,
668293,1318,1,352,2230,
668316,0,430,1,107,
66842231,16,0,430,1,
66851114,1343,1,118,2232,
668616,0,430,1,1123,
66872233,16,0,430,1,
6688371,1365,1,1628,2234,
668916,0,430,1,375,
66901376,1,1882,2235,16,
66910,430,1,377,1381,
66921,379,1386,1,380,
66931391,1,883,2236,16,
66940,430,1,373,1409,
66951,130,2237,16,0,
6696430,1,143,2238,16,
66970,430,1,387,2239,
669816,0,430,1,2664,
66992240,16,0,430,1,
67001159,2241,16,0,430,
67011,157,2242,16,0,
6702430,1,1413,2243,16,
67030,430,1,1665,2244,
670416,0,430,1,412,
67052245,16,0,430,1,
67061377,2246,16,0,430,
67071,172,2247,16,0,
6708430,1,1939,2248,16,
67090,430,1,437,2249,
671016,0,430,1,188,
67112250,16,0,430,1,
6712942,2251,16,0,430,
67131,1195,2252,16,0,
6714430,1,1449,2253,16,
67150,430,1,1701,2254,
671616,0,430,1,447,
67171511,1,205,2255,16,
67180,430,1,827,2256,
671916,0,430,1,223,
67202257,16,0,430,1,
6721476,1543,1,477,1549,
67221,1231,2258,16,0,
6723430,1,479,1559,1,
6724480,1564,1,1485,2259,
672516,0,430,1,1737,
67262260,16,0,430,1,
6727242,2261,16,0,430,
67281,478,1583,1,1001,
67291588,1,1002,1593,1,
673022,2262,19,383,1,
673122,2263,5,84,1,
67321011,1102,1,1012,2264,
673316,0,381,1,1013,
67341258,1,262,1119,1,
67351267,2265,16,0,381,
67361,515,2266,16,0,
6737381,1,1521,2267,16,
67380,381,1,525,1216,
67391,283,1172,1,2299,
67402268,16,0,381,1,
674142,2269,16,0,381,
67421,40,1177,1,44,
67431183,1,47,1184,1,
67441303,2270,16,0,381,
67451,1555,2271,16,0,
6746381,1,50,1201,1,
674748,1190,1,49,1196,
67481,51,1206,1,63,
67491222,1,305,1211,1,
675066,1228,1,67,1233,
67511,68,1238,1,69,
67521243,1,70,1248,1,
675373,2272,16,0,381,
67541,74,1253,1,328,
67552273,16,0,381,1,
67561048,2274,16,0,381,
67571,82,2275,16,0,
6758381,1,1840,2276,16,
67590,381,1,1591,2277,
676016,0,381,1,1341,
67612278,16,0,381,1,
67621096,1312,1,93,1318,
67631,352,2279,16,0,
6764381,1,107,2280,16,
67650,381,1,1114,1343,
67661,118,2281,16,0,
6767381,1,1123,2282,16,
67680,381,1,371,1365,
67691,1628,2283,16,0,
6770381,1,375,1376,1,
67711882,2284,16,0,381,
67721,377,1381,1,379,
67731386,1,380,1391,1,
6774883,2285,16,0,381,
67751,373,1409,1,130,
67762286,16,0,381,1,
6777143,2287,16,0,381,
67781,387,2288,16,0,
6779381,1,2664,2289,16,
67800,381,1,1159,2290,
678116,0,381,1,157,
67822291,16,0,381,1,
67831413,2292,16,0,381,
67841,1665,2293,16,0,
6785381,1,412,2294,16,
67860,381,1,1377,2295,
678716,0,381,1,172,
67882296,16,0,381,1,
67891939,2297,16,0,381,
67901,437,2298,16,0,
6791381,1,188,2299,16,
67920,381,1,942,2300,
679316,0,381,1,1195,
67942301,16,0,381,1,
67951449,2302,16,0,381,
67961,1701,2303,16,0,
6797381,1,447,1511,1,
6798205,2304,16,0,381,
67991,827,2305,16,0,
6800381,1,223,2306,16,
68010,381,1,476,1543,
68021,477,1549,1,1231,
68032307,16,0,381,1,
6804479,1559,1,480,1564,
68051,1485,2308,16,0,
6806381,1,1737,2309,16,
68070,381,1,242,2310,
680816,0,381,1,478,
68091583,1,1001,1588,1,
68101002,1593,1,23,2311,
681119,504,1,23,2312,
68125,38,1,1901,2313,
681316,0,502,1,2075,
68142314,16,0,502,1,
68151860,821,1,1803,787,
68161,1804,2315,16,0,
6817502,1,2413,2316,16,
68180,502,1,2198,2317,
681916,0,502,1,1873,
6820835,1,1657,894,1,
68211989,916,1,1990,2318,
682216,0,502,1,1775,
68232319,16,0,502,1,
682432,2320,16,0,502,
68251,2105,814,1,2106,
68262321,16,0,502,1,
68272364,827,1,2227,908,
68281,2337,2322,16,0,
6829502,1,2021,718,1,
68302458,876,1,2459,882,
68311,2462,889,1,2136,
6832842,1,2464,899,1,
68332029,725,1,2030,731,
68341,2031,736,1,2032,
6835741,1,2033,746,1,
68362035,752,1,2037,757,
68371,2039,762,1,1931,
6838861,1,2041,768,1,
68392043,774,1,2045,779,
68401,1574,799,1,1958,
68412323,16,0,502,1,
684224,2324,19,177,1,
684324,2325,5,5,1,
684444,2326,16,0,175,
68451,377,2327,16,0,
6846540,1,40,2328,16,
68470,674,1,63,2329,
684816,0,196,1,373,
68492330,16,0,536,1,
685025,2331,19,291,1,
685125,2332,5,177,1,
6852256,2333,16,0,545,
68531,1261,2334,16,0,
6854545,1,1011,1102,1,
68551012,2335,16,0,289,
68561,2458,876,1,262,
68571119,1,1267,2336,16,
68580,289,1,2021,718,
68591,1521,2337,16,0,
6860289,1,1775,2338,16,
68610,545,1,2029,725,
68621,2030,731,1,2031,
6863736,1,2032,741,1,
68642033,746,1,277,2339,
686516,0,545,1,2035,
6866752,1,2037,757,1,
68672039,762,1,32,2340,
686816,0,545,1,2464,
6869899,1,2293,2341,16,
68700,545,1,2043,774,
68711,2045,779,1,2299,
68722342,16,0,289,1,
687341,2343,16,0,545,
68741,42,2344,16,0,
6875289,1,40,1177,1,
687644,1183,1,43,2345,
687716,0,545,1,1804,
68782346,16,0,545,1,
687948,1190,1,49,1196,
68801,47,1184,1,51,
68811206,1,52,2347,16,
68820,545,1,50,1201,
68831,305,1211,1,1096,
68841312,1,1515,2348,16,
68850,545,1,2318,2349,
688616,0,545,1,62,
68872350,16,0,545,1,
688863,1222,1,66,1228,
68891,67,1233,1,68,
68901238,1,69,1243,1,
689170,1248,1,71,2351,
689216,0,545,1,283,
68931172,1,73,2352,16,
68940,289,1,74,1253,
68951,1013,1258,1,76,
68962353,16,0,545,1,
68971834,2354,16,0,545,
68981,2337,2355,16,0,
6899545,1,79,2356,16,
69000,545,1,1335,2357,
690116,0,545,1,299,
69022358,16,0,545,1,
690382,2359,16,0,289,
69041,1840,2360,16,0,
6905289,1,1297,2361,16,
69060,545,1,85,2362,
690716,0,545,1,1341,
69082363,16,0,289,1,
690989,2364,16,0,545,
69101,1303,2365,16,0,
6911289,1,509,2366,16,
69120,545,1,93,1318,
69131,322,2367,16,0,
6914545,1,97,2368,16,
69150,545,1,2041,768,
69161,1555,2369,16,0,
6917289,1,827,2370,16,
69180,289,1,102,2371,
691916,0,545,1,1860,
6920821,1,1803,787,1,
69212364,827,1,107,2372,
692216,0,289,1,1114,
69231343,1,112,2373,16,
69240,545,1,1117,2374,
692516,0,545,1,352,
69261349,1,1873,835,1,
6927118,1355,1,1123,2375,
692816,0,289,1,371,
69291365,1,515,2376,16,
69300,289,1,1377,2377,
693116,0,289,1,124,
69322378,16,0,545,1,
69331882,2379,16,0,289,
69341,377,1381,1,379,
69351386,1,380,1391,1,
6936130,1414,1,346,2380,
693716,0,545,1,2075,
69382381,16,0,545,1,
6939373,1409,1,387,2382,
694016,0,289,1,137,
69412383,16,0,545,1,
6942143,2384,16,0,289,
69431,1901,2385,16,0,
6944545,1,1048,1344,1,
69452658,2386,16,0,545,
69461,1153,2387,16,0,
6947545,1,375,1376,1,
6948151,2388,16,0,545,
69491,1407,2389,16,0,
6950545,1,1659,2390,16,
69510,545,1,2413,2391,
695216,0,545,1,1159,
69532392,16,0,289,1,
6954381,2393,16,0,545,
69551,157,2394,16,0,
6956289,1,1413,2395,16,
69570,289,1,883,2396,
695816,0,289,1,1371,
69592397,16,0,545,1,
6960328,1302,1,2105,814,
69611,2106,2398,16,0,
6962545,1,166,2399,16,
69630,545,1,525,2400,
696416,0,545,1,1622,
69652401,16,0,545,1,
6966406,2402,16,0,545,
69671,1574,799,1,172,
69681469,1,1931,861,1,
6969412,2403,16,0,289,
69701,1933,2404,16,0,
6971545,1,1876,2405,16,
69720,545,1,431,2406,
697316,0,545,1,1585,
69742407,16,0,545,1,
6975182,2408,16,0,545,
69761,1628,2409,16,0,
6977289,1,1189,2410,16,
69780,545,1,437,2411,
697916,0,289,1,1591,
69802412,16,0,289,1,
6981188,1518,1,1695,2413,
698216,0,545,1,2198,
69832414,16,0,545,1,
69841195,2415,16,0,289,
69851,1449,2416,16,0,
6986289,1,1701,2417,16,
69870,289,1,447,2418,
698816,0,545,1,199,
69892419,16,0,545,1,
69902459,882,1,1958,2420,
699116,0,545,1,2462,
6992889,1,1657,894,1,
6993205,2421,16,0,289,
69941,459,2422,16,0,
6995545,1,462,2423,16,
69960,545,1,1665,2424,
699716,0,289,1,217,
69982425,16,0,545,1,
69992227,908,1,942,1490,
70001,1225,2426,16,0,
7001545,1,223,2427,16,
70020,289,1,1479,2428,
700316,0,545,1,1731,
70042429,16,0,545,1,
7005477,1549,1,1231,2430,
700616,0,289,1,479,
70071559,1,480,1564,1,
70081485,2431,16,0,289,
70091,1737,2432,16,0,
7010289,1,1989,916,1,
70111990,2433,16,0,545,
70121,1443,2434,16,0,
7013545,1,236,2435,16,
70140,545,1,2136,842,
70151,2664,2436,16,0,
7016289,1,476,1543,1,
7017242,2437,16,0,289,
70181,478,1583,1,1939,
70192438,16,0,289,1,
70201001,1588,1,1002,1593,
70211,1756,2439,16,0,
7022545,1,26,2440,19,
7023308,1,26,2441,5,
702484,1,1011,1102,1,
70251012,2442,16,0,306,
70261,1013,1258,1,262,
70271119,1,1267,2443,16,
70280,306,1,515,2444,
702916,0,660,1,1521,
70302445,16,0,306,1,
7031525,1216,1,283,1172,
70321,2299,2446,16,0,
7033306,1,42,2447,16,
70340,306,1,40,1177,
70351,44,1183,1,47,
70361184,1,1303,2448,16,
70370,306,1,1555,2449,
703816,0,306,1,50,
70391201,1,48,1190,1,
704049,1196,1,51,1206,
70411,63,1222,1,305,
70421211,1,66,1228,1,
704367,1233,1,68,1238,
70441,69,1243,1,70,
70451248,1,73,2450,16,
70460,306,1,74,1253,
70471,328,1302,1,1048,
70481344,1,82,2451,16,
70490,306,1,1840,2452,
705016,0,306,1,1591,
70512453,16,0,306,1,
70521341,2454,16,0,306,
70531,1096,1312,1,93,
70541318,1,352,1349,1,
7055107,2455,16,0,306,
70561,1114,1343,1,118,
70571355,1,1123,2456,16,
70580,306,1,371,1365,
70591,1628,2457,16,0,
7060306,1,375,1376,1,
70611882,2458,16,0,306,
70621,377,1381,1,379,
70631386,1,380,1391,1,
7064883,2459,16,0,306,
70651,373,1409,1,130,
70661414,1,143,2460,16,
70670,306,1,387,2461,
706816,0,306,1,2664,
70692462,16,0,306,1,
70701159,2463,16,0,306,
70711,157,2464,16,0,
7072306,1,1413,2465,16,
70730,306,1,1665,2466,
707416,0,306,1,412,
70752467,16,0,306,1,
70761377,2468,16,0,306,
70771,172,1469,1,1939,
70782469,16,0,306,1,
7079437,2470,16,0,588,
70801,188,1518,1,942,
70811490,1,1195,2471,16,
70820,306,1,1449,2472,
708316,0,306,1,1701,
70842473,16,0,306,1,
7085447,1511,1,205,2474,
708616,0,306,1,827,
70872475,16,0,306,1,
7088223,2476,16,0,306,
70891,476,1543,1,477,
70901549,1,1231,2477,16,
70910,306,1,479,1559,
70921,480,1564,1,1485,
70932478,16,0,306,1,
70941737,2479,16,0,306,
70951,242,2480,16,0,
7096306,1,478,1583,1,
70971001,1588,1,1002,1593,
70981,27,2481,19,598,
70991,27,2482,5,95,
71001,256,2483,16,0,
7101596,1,1261,2484,16,
71020,596,1,509,2485,
710316,0,596,1,1515,
71042486,16,0,596,1,
71052021,718,1,1775,2487,
710616,0,596,1,2029,
7107725,1,2030,731,1,
71082031,736,1,2032,741,
71091,2033,746,1,277,
71102488,16,0,596,1,
71112035,752,1,2037,757,
71121,2039,762,1,32,
71132489,16,0,596,1,
71142041,768,1,2293,2490,
711516,0,596,1,2043,
7116774,1,2045,779,1,
711741,2491,16,0,596,
71181,1297,2492,16,0,
7119596,1,43,2493,16,
71200,596,1,1803,787,
71211,1804,2494,16,0,
7122596,1,299,2495,16,
71230,596,1,52,2496,
712416,0,596,1,2318,
71252497,16,0,596,1,
712662,2498,16,0,596,
71271,2075,2499,16,0,
7128596,1,1574,799,1,
712971,2500,16,0,596,
71301,76,2501,16,0,
7131596,1,1834,2502,16,
71320,596,1,2337,2503,
713316,0,596,1,79,
71342504,16,0,596,1,
71351335,2505,16,0,596,
71361,322,2506,16,0,
7137596,1,85,2507,16,
71380,596,1,89,2508,
713916,0,596,1,346,
71402509,16,0,596,1,
71412105,814,1,2106,2510,
714216,0,596,1,97,
71432511,16,0,596,1,
71441860,821,1,2364,827,
71451,102,2512,16,0,
7146596,1,112,2513,16,
71470,596,1,1117,2514,
714816,0,596,1,1873,
7149835,1,1876,2515,16,
71500,596,1,124,2516,
715116,0,596,1,2136,
7152842,1,381,2517,16,
71530,596,1,525,2518,
715416,0,596,1,137,
71552519,16,0,596,1,
71561901,2520,16,0,596,
71571,2658,2521,16,0,
7158596,1,1153,2522,16,
71590,596,1,151,2523,
716016,0,596,1,1407,
71612524,16,0,596,1,
71621659,2525,16,0,596,
71631,2413,2526,16,0,
7164596,1,406,2527,16,
71650,596,1,1371,2528,
716616,0,596,1,166,
71672529,16,0,596,1,
71681622,2530,16,0,596,
71691,1931,861,1,1933,
71702531,16,0,596,1,
7171431,2532,16,0,596,
71721,1585,2533,16,0,
7173596,1,182,2534,16,
71740,596,1,1189,2535,
717516,0,596,1,1443,
71762536,16,0,596,1,
71771695,2537,16,0,596,
71781,2198,2538,16,0,
7179596,1,447,2539,16,
71800,596,1,2458,876,
71811,2459,882,1,1958,
71822540,16,0,596,1,
71832462,889,1,1657,894,
71841,2464,899,1,199,
71852541,16,0,596,1,
7186459,2542,16,0,596,
71871,462,2543,16,0,
7188596,1,217,2544,16,
71890,596,1,2227,908,
71901,1225,2545,16,0,
7191596,1,1479,2546,16,
71920,596,1,1731,2547,
719316,0,596,1,1989,
7194916,1,1990,2548,16,
71950,596,1,236,2549,
719616,0,596,1,1756,
71972550,16,0,596,1,
719828,2551,19,629,1,
719928,2552,5,60,1,
7200328,1302,1,223,1533,
72011,1096,1312,1,118,
72021355,1,883,1397,1,
7203525,1216,1,1001,1588,
72041,130,1414,1,459,
72051688,1,1114,1343,1,
7206352,1349,1,447,1511,
72071,464,1683,1,1011,
72081102,1,1013,1258,1,
7209242,1578,1,143,1419,
72101,40,1177,1,41,
72111659,1,42,1662,1,
7212479,1559,1,44,1183,
72131,481,1646,1,373,
72141409,1,47,1184,1,
7215157,1443,1,49,1196,
72161,50,1201,1,48,
72171190,1,379,1386,1,
7218380,1391,1,51,1206,
72191,476,1543,1,371,
72201365,1,478,1583,1,
72211048,1344,1,375,1376,
72221,172,1469,1,262,
72231119,1,283,1172,1,
722463,1222,1,67,1233,
72251,68,1238,1,69,
72261243,1,66,1228,1,
7227461,2553,16,0,627,
72281,74,1253,1,377,
72291381,1,1002,1593,1,
723070,1248,1,188,1518,
72311,82,1280,1,305,
72321211,1,477,1549,1,
7233827,1331,1,93,1318,
72341,480,1564,1,205,
72351523,1,942,1490,1,
7236107,1338,1,29,2554,
723719,280,1,29,2555,
72385,84,1,1011,1102,
72391,1012,2556,16,0,
7240278,1,1013,1258,1,
7241262,1119,1,1267,2557,
724216,0,278,1,515,
72432558,16,0,278,1,
72441521,2559,16,0,278,
72451,525,1216,1,283,
72461172,1,2299,2560,16,
72470,278,1,42,2561,
724816,0,278,1,40,
72491177,1,44,1183,1,
725047,1184,1,1303,2562,
725116,0,278,1,1555,
72522563,16,0,278,1,
725350,1201,1,48,1190,
72541,49,1196,1,51,
72551206,1,63,1222,1,
7256305,1211,1,66,1228,
72571,67,1233,1,68,
72581238,1,69,1243,1,
725970,1248,1,73,2564,
726016,0,278,1,74,
72611253,1,328,1302,1,
72621048,1344,1,82,2565,
726316,0,278,1,1840,
72642566,16,0,278,1,
72651591,2567,16,0,278,
72661,1341,2568,16,0,
7267278,1,1096,1312,1,
726893,1318,1,352,1349,
72691,107,2569,16,0,
7270278,1,1114,1343,1,
7271118,1355,1,1123,2570,
727216,0,278,1,371,
72731365,1,1628,2571,16,
72740,278,1,375,1376,
72751,1882,2572,16,0,
7276278,1,377,1381,1,
7277379,1386,1,380,1391,
72781,883,2573,16,0,
7279278,1,373,1409,1,
7280130,1414,1,143,1419,
72811,387,2574,16,0,
7282278,1,2664,2575,16,
72830,278,1,1159,2576,
728416,0,278,1,157,
72851443,1,1413,2577,16,
72860,278,1,1665,2578,
728716,0,278,1,412,
72882579,16,0,278,1,
72891377,2580,16,0,278,
72901,172,1469,1,1939,
72912581,16,0,278,1,
7292437,2582,16,0,278,
72931,188,1518,1,942,
72941490,1,1195,2583,16,
72950,278,1,1449,2584,
729616,0,278,1,1701,
72972585,16,0,278,1,
7298447,1511,1,205,2586,
729916,0,278,1,827,
73002587,16,0,278,1,
7301223,2588,16,0,278,
73021,476,1543,1,477,
73031549,1,1231,2589,16,
73040,278,1,479,1559,
73051,480,1564,1,1485,
73062590,16,0,278,1,
73071737,2591,16,0,278,
73081,242,2592,16,0,
7309278,1,478,1583,1,
73101001,1588,1,1002,1593,
73111,30,2593,19,268,
73121,30,2594,5,84,
73131,1011,1102,1,1012,
73142595,16,0,266,1,
73151013,1258,1,262,1119,
73161,1267,2596,16,0,
7317266,1,515,2597,16,
73180,266,1,1521,2598,
731916,0,266,1,525,
73201216,1,283,1172,1,
73212299,2599,16,0,266,
73221,42,2600,16,0,
7323266,1,40,1177,1,
732444,1183,1,47,1184,
73251,1303,2601,16,0,
7326266,1,1555,2602,16,
73270,266,1,50,1201,
73281,48,1190,1,49,
73291196,1,51,1206,1,
733063,1222,1,305,1211,
73311,66,1228,1,67,
73321233,1,68,1238,1,
733369,1243,1,70,1248,
73341,73,2603,16,0,
7335266,1,74,1253,1,
7336328,1302,1,1048,1344,
73371,82,2604,16,0,
7338266,1,1840,2605,16,
73390,266,1,1591,2606,
734016,0,266,1,1341,
73412607,16,0,266,1,
73421096,1312,1,93,1318,
73431,352,1349,1,107,
73442608,16,0,266,1,
73451114,1343,1,118,1355,
73461,1123,2609,16,0,
7347266,1,371,1365,1,
73481628,2610,16,0,266,
73491,375,1376,1,1882,
73502611,16,0,266,1,
7351377,1381,1,379,1386,
73521,380,1391,1,883,
73532612,16,0,266,1,
7354373,1409,1,130,1414,
73551,143,1419,1,387,
73562613,16,0,266,1,
73572664,2614,16,0,266,
73581,1159,2615,16,0,
7359266,1,157,1443,1,
73601413,2616,16,0,266,
73611,1665,2617,16,0,
7362266,1,412,2618,16,
73630,266,1,1377,2619,
736416,0,266,1,172,
73651469,1,1939,2620,16,
73660,266,1,437,2621,
736716,0,266,1,188,
73681518,1,942,1490,1,
73691195,2622,16,0,266,
73701,1449,2623,16,0,
7371266,1,1701,2624,16,
73720,266,1,447,1511,
73731,205,2625,16,0,
7374266,1,827,2626,16,
73750,266,1,223,2627,
737616,0,266,1,476,
73771543,1,477,1549,1,
73781231,2628,16,0,266,
73791,479,1559,1,480,
73801564,1,1485,2629,16,
73810,266,1,1737,2630,
738216,0,266,1,242,
73832631,16,0,266,1,
7384478,1583,1,1001,1588,
73851,1002,1593,1,31,
73862632,19,253,1,31,
73872633,5,84,1,1011,
73881102,1,1012,2634,16,
73890,251,1,1013,1258,
73901,262,1119,1,1267,
73912635,16,0,251,1,
7392515,2636,16,0,251,
73931,1521,2637,16,0,
7394251,1,525,1216,1,
7395283,1172,1,2299,2638,
739616,0,251,1,42,
73972639,16,0,251,1,
739840,1177,1,44,1183,
73991,47,1184,1,1303,
74002640,16,0,251,1,
74011555,2641,16,0,251,
74021,50,1201,1,48,
74031190,1,49,1196,1,
740451,1206,1,63,1222,
74051,305,1211,1,66,
74061228,1,67,1233,1,
740768,1238,1,69,1243,
74081,70,1248,1,73,
74092642,16,0,251,1,
741074,1253,1,328,1302,
74111,1048,1344,1,82,
74122643,16,0,251,1,
74131840,2644,16,0,251,
74141,1591,2645,16,0,
7415251,1,1341,2646,16,
74160,251,1,1096,1312,
74171,93,1318,1,352,
74181349,1,107,2647,16,
74190,251,1,1114,1343,
74201,118,1355,1,1123,
74212648,16,0,251,1,
7422371,1365,1,1628,2649,
742316,0,251,1,375,
74241376,1,1882,2650,16,
74250,251,1,377,1381,
74261,379,1386,1,380,
74271391,1,883,2651,16,
74280,251,1,373,1409,
74291,130,1414,1,143,
74302652,16,0,251,1,
7431387,2653,16,0,251,
74321,2664,2654,16,0,
7433251,1,1159,2655,16,
74340,251,1,157,2656,
743516,0,251,1,1413,
74362657,16,0,251,1,
74371665,2658,16,0,251,
74381,412,2659,16,0,
7439251,1,1377,2660,16,
74400,251,1,172,1469,
74411,1939,2661,16,0,
7442251,1,437,2662,16,
74430,251,1,188,1518,
74441,942,1490,1,1195,
74452663,16,0,251,1,
74461449,2664,16,0,251,
74471,1701,2665,16,0,
7448251,1,447,1511,1,
7449205,2666,16,0,251,
74501,827,2667,16,0,
7451251,1,223,2668,16,
74520,251,1,476,1543,
74531,477,1549,1,1231,
74542669,16,0,251,1,
7455479,1559,1,480,1564,
74561,1485,2670,16,0,
7457251,1,1737,2671,16,
74580,251,1,242,2672,
745916,0,251,1,478,
74601583,1,1001,1588,1,
74611002,1593,1,32,2673,
746219,246,1,32,2674,
74635,84,1,1011,1102,
74641,1012,2675,16,0,
7465244,1,1013,1258,1,
7466262,1119,1,1267,2676,
746716,0,244,1,515,
74682677,16,0,244,1,
74691521,2678,16,0,244,
74701,525,1216,1,283,
74711172,1,2299,2679,16,
74720,244,1,42,2680,
747316,0,244,1,40,
74741177,1,44,1183,1,
747547,1184,1,1303,2681,
747616,0,244,1,1555,
74772682,16,0,244,1,
747850,1201,1,48,1190,
74791,49,1196,1,51,
74801206,1,63,1222,1,
7481305,1211,1,66,1228,
74821,67,1233,1,68,
74831238,1,69,1243,1,
748470,1248,1,73,2683,
748516,0,244,1,74,
74861253,1,328,1302,1,
74871048,1344,1,82,2684,
748816,0,244,1,1840,
74892685,16,0,244,1,
74901591,2686,16,0,244,
74911,1341,2687,16,0,
7492244,1,1096,1312,1,
749393,1318,1,352,1349,
74941,107,2688,16,0,
7495244,1,1114,1343,1,
7496118,1355,1,1123,2689,
749716,0,244,1,371,
74981365,1,1628,2690,16,
74990,244,1,375,1376,
75001,1882,2691,16,0,
7501244,1,377,1381,1,
7502379,1386,1,380,1391,
75031,883,2692,16,0,
7504244,1,373,1409,1,
7505130,1414,1,143,2693,
750616,0,244,1,387,
75072694,16,0,244,1,
75082664,2695,16,0,244,
75091,1159,2696,16,0,
7510244,1,157,2697,16,
75110,244,1,1413,2698,
751216,0,244,1,1665,
75132699,16,0,244,1,
7514412,2700,16,0,244,
75151,1377,2701,16,0,
7516244,1,172,1469,1,
75171939,2702,16,0,244,
75181,437,2703,16,0,
7519244,1,188,1518,1,
7520942,1490,1,1195,2704,
752116,0,244,1,1449,
75222705,16,0,244,1,
75231701,2706,16,0,244,
75241,447,1511,1,205,
75252707,16,0,244,1,
7526827,2708,16,0,244,
75271,223,2709,16,0,
7528244,1,476,1543,1,
7529477,1549,1,1231,2710,
753016,0,244,1,479,
75311559,1,480,1564,1,
75321485,2711,16,0,244,
75331,1737,2712,16,0,
7534244,1,242,2713,16,
75350,244,1,478,1583,
75361,1001,1588,1,1002,
75371593,1,33,2714,19,
7538332,1,33,2715,5,
753984,1,1011,1102,1,
75401012,2716,16,0,330,
75411,1013,1258,1,262,
75421119,1,1267,2717,16,
75430,330,1,515,2718,
754416,0,330,1,1521,
75452719,16,0,330,1,
7546525,1216,1,283,1172,
75471,2299,2720,16,0,
7548330,1,42,2721,16,
75490,330,1,40,1177,
75501,44,1183,1,47,
75511184,1,1303,2722,16,
75520,330,1,1555,2723,
755316,0,330,1,50,
75541201,1,48,1190,1,
755549,1196,1,51,1206,
75561,63,1222,1,305,
75571211,1,66,1228,1,
755867,1233,1,68,1238,
75591,69,1243,1,70,
75601248,1,73,2724,16,
75610,330,1,74,1253,
75621,328,1302,1,1048,
75631344,1,82,2725,16,
75640,330,1,1840,2726,
756516,0,330,1,1591,
75662727,16,0,330,1,
75671341,2728,16,0,330,
75681,1096,1312,1,93,
75691318,1,352,1349,1,
7570107,2729,16,0,330,
75711,1114,1343,1,118,
75721355,1,1123,2730,16,
75730,330,1,371,1365,
75741,1628,2731,16,0,
7575330,1,375,1376,1,
75761882,2732,16,0,330,
75771,377,1381,1,379,
75781386,1,380,1391,1,
7579883,2733,16,0,330,
75801,373,1409,1,130,
75811414,1,143,1419,1,
7582387,2734,16,0,330,
75831,2664,2735,16,0,
7584330,1,1159,2736,16,
75850,330,1,157,1443,
75861,1413,2737,16,0,
7587330,1,1665,2738,16,
75880,330,1,412,2739,
758916,0,330,1,1377,
75902740,16,0,330,1,
7591172,1469,1,1939,2741,
759216,0,330,1,437,
75932742,16,0,330,1,
7594188,1518,1,942,1490,
75951,1195,2743,16,0,
7596330,1,1449,2744,16,
75970,330,1,1701,2745,
759816,0,330,1,447,
75991511,1,205,2746,16,
76000,330,1,827,2747,
760116,0,330,1,223,
76022748,16,0,330,1,
7603476,1543,1,477,1549,
76041,1231,2749,16,0,
7605330,1,479,1559,1,
7606480,1564,1,1485,2750,
760716,0,330,1,1737,
76082751,16,0,330,1,
7609242,1578,1,478,1583,
76101,1001,1588,1,1002,
76111593,1,34,2752,19,
7612322,1,34,2753,5,
761384,1,1011,1102,1,
76141012,2754,16,0,320,
76151,1013,1258,1,262,
76161119,1,1267,2755,16,
76170,320,1,515,2756,
761816,0,320,1,1521,
76192757,16,0,320,1,
7620525,1216,1,283,1172,
76211,2299,2758,16,0,
7622320,1,42,2759,16,
76230,320,1,40,1177,
76241,44,1183,1,47,
76251184,1,1303,2760,16,
76260,320,1,1555,2761,
762716,0,320,1,50,
76281201,1,48,1190,1,
762949,1196,1,51,1206,
76301,63,1222,1,305,
76311211,1,66,1228,1,
763267,1233,1,68,1238,
76331,69,1243,1,70,
76341248,1,73,2762,16,
76350,320,1,74,1253,
76361,328,1302,1,1048,
76371344,1,82,2763,16,
76380,320,1,1840,2764,
763916,0,320,1,1591,
76402765,16,0,320,1,
76411341,2766,16,0,320,
76421,1096,1312,1,93,
76431318,1,352,1349,1,
7644107,2767,16,0,320,
76451,1114,1343,1,118,
76461355,1,1123,2768,16,
76470,320,1,371,1365,
76481,1628,2769,16,0,
7649320,1,375,1376,1,
76501882,2770,16,0,320,
76511,377,1381,1,379,
76521386,1,380,1391,1,
7653883,2771,16,0,320,
76541,373,1409,1,130,
76551414,1,143,1419,1,
7656387,2772,16,0,320,
76571,2664,2773,16,0,
7658320,1,1159,2774,16,
76590,320,1,157,1443,
76601,1413,2775,16,0,
7661320,1,1665,2776,16,
76620,320,1,412,2777,
766316,0,320,1,1377,
76642778,16,0,320,1,
7665172,1469,1,1939,2779,
766616,0,320,1,437,
76672780,16,0,320,1,
7668188,1518,1,942,1490,
76691,1195,2781,16,0,
7670320,1,1449,2782,16,
76710,320,1,1701,2783,
767216,0,320,1,447,
76731511,1,205,1523,1,
7674827,2784,16,0,320,
76751,223,1533,1,476,
76761543,1,477,1549,1,
76771231,2785,16,0,320,
76781,479,1559,1,480,
76791564,1,1485,2786,16,
76800,320,1,1737,2787,
768116,0,320,1,242,
76821578,1,478,1583,1,
76831001,1588,1,1002,1593,
76841,35,2788,19,311,
76851,35,2789,5,84,
76861,1011,1102,1,1012,
76872790,16,0,309,1,
76881013,1258,1,262,1119,
76891,1267,2791,16,0,
7690309,1,515,2792,16,
76910,309,1,1521,2793,
769216,0,309,1,525,
76931216,1,283,1172,1,
76942299,2794,16,0,309,
76951,42,2795,16,0,
7696309,1,40,1177,1,
769744,1183,1,47,1184,
76981,1303,2796,16,0,
7699309,1,1555,2797,16,
77000,309,1,50,1201,
77011,48,1190,1,49,
77021196,1,51,1206,1,
770363,1222,1,305,1211,
77041,66,1228,1,67,
77051233,1,68,1238,1,
770669,1243,1,70,1248,
77071,73,2798,16,0,
7708309,1,74,1253,1,
7709328,1302,1,1048,1344,
77101,82,2799,16,0,
7711309,1,1840,2800,16,
77120,309,1,1591,2801,
771316,0,309,1,1341,
77142802,16,0,309,1,
77151096,1312,1,93,1318,
77161,352,1349,1,107,
77172803,16,0,309,1,
77181114,1343,1,118,1355,
77191,1123,2804,16,0,
7720309,1,371,1365,1,
77211628,2805,16,0,309,
77221,375,1376,1,1882,
77232806,16,0,309,1,
7724377,1381,1,379,1386,
77251,380,1391,1,883,
77262807,16,0,309,1,
7727373,1409,1,130,1414,
77281,143,1419,1,387,
77292808,16,0,309,1,
77302664,2809,16,0,309,
77311,1159,2810,16,0,
7732309,1,157,1443,1,
77331413,2811,16,0,309,
77341,1665,2812,16,0,
7735309,1,412,2813,16,
77360,309,1,1377,2814,
773716,0,309,1,172,
77381469,1,1939,2815,16,
77390,309,1,437,2816,
774016,0,309,1,188,
77411518,1,942,1490,1,
77421195,2817,16,0,309,
77431,1449,2818,16,0,
7744309,1,1701,2819,16,
77450,309,1,447,1511,
77461,205,1523,1,827,
77472820,16,0,309,1,
7748223,2821,16,0,309,
77491,476,1543,1,477,
77501549,1,1231,2822,16,
77510,309,1,479,1559,
77521,480,1564,1,1485,
77532823,16,0,309,1,
77541737,2824,16,0,309,
77551,242,1578,1,478,
77561583,1,1001,1588,1,
77571002,1593,1,36,2825,
775819,216,1,36,2826,
77595,94,1,256,2827,
776016,0,214,1,1261,
77612828,16,0,214,1,
7762509,2829,16,0,214,
77631,1515,2830,16,0,
7764214,1,2021,718,1,
77651775,2831,16,0,214,
77661,2029,725,1,2030,
7767731,1,2031,736,1,
77682032,741,1,2033,746,
77691,277,2832,16,0,
7770214,1,2035,752,1,
77712037,757,1,2039,762,
77721,32,2833,16,0,
7773214,1,2041,768,1,
77742293,2834,16,0,214,
77751,2043,774,1,2045,
7776779,1,41,2835,16,
77770,214,1,1297,2836,
777816,0,214,1,43,
77792837,16,0,214,1,
77801803,787,1,1804,2838,
778116,0,214,1,299,
77822839,16,0,214,1,
778352,2840,16,0,214,
77841,2318,2841,16,0,
7785214,1,2075,2842,16,
77860,214,1,1574,799,
77871,71,2843,16,0,
7788214,1,76,2844,16,
77890,214,1,1834,2845,
779016,0,214,1,2337,
77912846,16,0,214,1,
779279,2847,16,0,214,
77931,1335,2848,16,0,
7794214,1,322,2849,16,
77950,214,1,85,2850,
779616,0,214,1,89,
77972851,16,0,214,1,
7798346,2852,16,0,214,
77991,2105,814,1,2106,
78002853,16,0,214,1,
780197,2854,16,0,214,
78021,1860,821,1,2364,
7803827,1,102,2855,16,
78040,214,1,112,2856,
780516,0,214,1,1117,
78062857,16,0,214,1,
78071873,835,1,1876,2858,
780816,0,214,1,124,
78092859,16,0,214,1,
78102136,842,1,381,2860,
781116,0,214,1,525,
78122861,16,0,214,1,
7813137,2862,16,0,214,
78141,1901,2863,16,0,
7815214,1,2658,2864,16,
78160,214,1,1153,2865,
781716,0,214,1,151,
78182866,16,0,214,1,
78191407,2867,16,0,214,
78201,1659,2868,16,0,
7821214,1,2413,2869,16,
78220,214,1,406,2870,
782316,0,214,1,1371,
78242871,16,0,214,1,
7825166,2872,16,0,214,
78261,1622,2873,16,0,
7827214,1,1931,861,1,
78281933,2874,16,0,214,
78291,431,2875,16,0,
7830214,1,1585,2876,16,
78310,214,1,182,2877,
783216,0,214,1,1189,
78332878,16,0,214,1,
78341443,2879,16,0,214,
78351,1695,2880,16,0,
7836214,1,2198,2881,16,
78370,214,1,447,2882,
783816,0,214,1,2458,
7839876,1,2459,882,1,
78401958,2883,16,0,214,
78411,2462,889,1,1657,
7842894,1,2464,899,1,
7843199,2884,16,0,214,
78441,459,2885,16,0,
7845214,1,462,2886,16,
78460,214,1,217,2887,
784716,0,214,1,2227,
7848908,1,1225,2888,16,
78490,214,1,1479,2889,
785016,0,214,1,1731,
78512890,16,0,214,1,
78521989,916,1,1990,2891,
785316,0,214,1,236,
78542892,16,0,214,1,
78551756,2893,16,0,214,
78561,37,2894,19,233,
78571,37,2895,5,94,
78581,256,2896,16,0,
7859231,1,1261,2897,16,
78600,231,1,509,2898,
786116,0,231,1,1515,
78622899,16,0,231,1,
78632021,718,1,1775,2900,
786416,0,231,1,2029,
7865725,1,2030,731,1,
78662031,736,1,2032,741,
78671,2033,746,1,277,
78682901,16,0,231,1,
78692035,752,1,2037,757,
78701,2039,762,1,32,
78712902,16,0,231,1,
78722041,768,1,2293,2903,
787316,0,231,1,2043,
7874774,1,2045,779,1,
787541,2904,16,0,231,
78761,1297,2905,16,0,
7877231,1,43,2906,16,
78780,231,1,1803,787,
78791,1804,2907,16,0,
7880231,1,299,2908,16,
78810,231,1,52,2909,
788216,0,231,1,2318,
78832910,16,0,231,1,
78842075,2911,16,0,231,
78851,1574,799,1,71,
78862912,16,0,231,1,
788776,2913,16,0,231,
78881,1834,2914,16,0,
7889231,1,2337,2915,16,
78900,231,1,79,2916,
789116,0,231,1,1335,
78922917,16,0,231,1,
7893322,2918,16,0,231,
78941,85,2919,16,0,
7895231,1,89,2920,16,
78960,231,1,346,2921,
789716,0,231,1,2105,
7898814,1,2106,2922,16,
78990,231,1,97,2923,
790016,0,231,1,1860,
7901821,1,2364,827,1,
7902102,2924,16,0,231,
79031,112,2925,16,0,
7904231,1,1117,2926,16,
79050,231,1,1873,835,
79061,1876,2927,16,0,
7907231,1,124,2928,16,
79080,231,1,2136,842,
79091,381,2929,16,0,
7910231,1,525,2930,16,
79110,231,1,137,2931,
791216,0,231,1,1901,
79132932,16,0,231,1,
79142658,2933,16,0,231,
79151,1153,2934,16,0,
7916231,1,151,2935,16,
79170,231,1,1407,2936,
791816,0,231,1,1659,
79192937,16,0,231,1,
79202413,2938,16,0,231,
79211,406,2939,16,0,
7922231,1,1371,2940,16,
79230,231,1,166,2941,
792416,0,231,1,1622,
79252942,16,0,231,1,
79261931,861,1,1933,2943,
792716,0,231,1,431,
79282944,16,0,231,1,
79291585,2945,16,0,231,
79301,182,2946,16,0,
7931231,1,1189,2947,16,
79320,231,1,1443,2948,
793316,0,231,1,1695,
79342949,16,0,231,1,
79352198,2950,16,0,231,
79361,447,2951,16,0,
7937231,1,2458,876,1,
79382459,882,1,1958,2952,
793916,0,231,1,2462,
7940889,1,1657,894,1,
79412464,899,1,199,2953,
794216,0,231,1,459,
79432954,16,0,231,1,
7944462,2955,16,0,231,
79451,217,2956,16,0,
7946231,1,2227,908,1,
79471225,2957,16,0,231,
79481,1479,2958,16,0,
7949231,1,1731,2959,16,
79500,231,1,1989,916,
79511,1990,2960,16,0,
7952231,1,236,2961,16,
79530,231,1,1756,2962,
795416,0,231,1,38,
79552963,19,230,1,38,
79562964,5,84,1,1011,
79571102,1,1012,2965,16,
79580,228,1,1013,1258,
79591,262,1119,1,1267,
79602966,16,0,228,1,
7961515,2967,16,0,228,
79621,1521,2968,16,0,
7963228,1,525,1216,1,
7964283,1172,1,2299,2969,
796516,0,228,1,42,
79662970,16,0,228,1,
796740,1177,1,44,1183,
79681,47,1184,1,1303,
79692971,16,0,228,1,
79701555,2972,16,0,228,
79711,50,1201,1,48,
79721190,1,49,1196,1,
797351,1206,1,63,1222,
79741,305,1211,1,66,
79751228,1,67,1233,1,
797668,1238,1,69,1243,
79771,70,1248,1,73,
79782973,16,0,228,1,
797974,1253,1,328,1302,
79801,1048,1344,1,82,
79812974,16,0,228,1,
79821840,2975,16,0,228,
79831,1591,2976,16,0,
7984228,1,1341,2977,16,
79850,228,1,1096,1312,
79861,93,1318,1,352,
79871349,1,107,2978,16,
79880,228,1,1114,1343,
79891,118,1355,1,1123,
79902979,16,0,228,1,
7991371,1365,1,1628,2980,
799216,0,228,1,375,
79931376,1,1882,2981,16,
79940,228,1,377,1381,
79951,379,1386,1,380,
79961391,1,883,1397,1,
7997373,1409,1,130,1414,
79981,143,1419,1,387,
79992982,16,0,228,1,
80002664,2983,16,0,228,
80011,1159,2984,16,0,
8002228,1,157,1443,1,
80031413,2985,16,0,228,
80041,1665,2986,16,0,
8005228,1,412,2987,16,
80060,228,1,1377,2988,
800716,0,228,1,172,
80081469,1,1939,2989,16,
80090,228,1,437,2990,
801016,0,228,1,188,
80111518,1,942,1490,1,
80121195,2991,16,0,228,
80131,1449,2992,16,0,
8014228,1,1701,2993,16,
80150,228,1,447,1511,
80161,205,1523,1,827,
80171331,1,223,1533,1,
8018476,1543,1,477,1549,
80191,1231,2994,16,0,
8020228,1,479,1559,1,
8021480,1564,1,1485,2995,
802216,0,228,1,1737,
80232996,16,0,228,1,
8024242,1578,1,478,1583,
80251,1001,1588,1,1002,
80261593,1,39,2997,19,
8027222,1,39,2998,5,
802884,1,1011,1102,1,
80291012,2999,16,0,220,
80301,1013,1258,1,262,
80311119,1,1267,3000,16,
80320,220,1,515,3001,
803316,0,220,1,1521,
80343002,16,0,220,1,
8035525,1216,1,283,1172,
80361,2299,3003,16,0,
8037220,1,42,3004,16,
80380,220,1,40,1177,
80391,44,1183,1,47,
80401184,1,1303,3005,16,
80410,220,1,1555,3006,
804216,0,220,1,50,
80431201,1,48,1190,1,
804449,1196,1,51,1206,
80451,63,1222,1,305,
80461211,1,66,1228,1,
804767,1233,1,68,1238,
80481,69,1243,1,70,
80491248,1,73,3007,16,
80500,220,1,74,1253,
80511,328,1302,1,1048,
80521344,1,82,3008,16,
80530,220,1,1840,3009,
805416,0,220,1,1591,
80553010,16,0,220,1,
80561341,3011,16,0,220,
80571,1096,1312,1,93,
80581318,1,352,1349,1,
8059107,3012,16,0,220,
80601,1114,1343,1,118,
80611355,1,1123,3013,16,
80620,220,1,371,1365,
80631,1628,3014,16,0,
8064220,1,375,1376,1,
80651882,3015,16,0,220,
80661,377,1381,1,379,
80671386,1,380,1391,1,
8068883,1397,1,373,1409,
80691,130,1414,1,143,
80701419,1,387,3016,16,
80710,220,1,2664,3017,
807216,0,220,1,1159,
80733018,16,0,220,1,
8074157,1443,1,1413,3019,
807516,0,220,1,1665,
80763020,16,0,220,1,
8077412,3021,16,0,220,
80781,1377,3022,16,0,
8079220,1,172,1469,1,
80801939,3023,16,0,220,
80811,437,3024,16,0,
8082220,1,188,1518,1,
8083942,1490,1,1195,3025,
808416,0,220,1,1449,
80853026,16,0,220,1,
80861701,3027,16,0,220,
80871,447,1511,1,205,
80881523,1,827,1331,1,
8089223,1533,1,476,1543,
80901,477,1549,1,1231,
80913028,16,0,220,1,
8092479,1559,1,480,1564,
80931,1485,3029,16,0,
8094220,1,1737,3030,16,
80950,220,1,242,1578,
80961,478,1583,1,1001,
80971588,1,1002,1593,1,
809840,3031,19,210,1,
809940,3032,5,84,1,
81001011,1102,1,1012,3033,
810116,0,208,1,1013,
81021258,1,262,1119,1,
81031267,3034,16,0,208,
81041,515,3035,16,0,
8105208,1,1521,3036,16,
81060,208,1,525,1216,
81071,283,1172,1,2299,
81083037,16,0,208,1,
810942,3038,16,0,208,
81101,40,1177,1,44,
81111183,1,47,1184,1,
81121303,3039,16,0,208,
81131,1555,3040,16,0,
8114208,1,50,1201,1,
811548,1190,1,49,1196,
81161,51,1206,1,63,
81171222,1,305,1211,1,
811866,1228,1,67,1233,
81191,68,1238,1,69,
81201243,1,70,1248,1,
812173,3041,16,0,208,
81221,74,1253,1,328,
81231302,1,1048,1344,1,
812482,3042,16,0,208,
81251,1840,3043,16,0,
8126208,1,1591,3044,16,
81270,208,1,1341,3045,
812816,0,208,1,1096,
81291312,1,93,1318,1,
8130352,1349,1,107,3046,
813116,0,208,1,1114,
81321343,1,118,3047,16,
81330,208,1,1123,3048,
813416,0,208,1,371,
81351365,1,1628,3049,16,
81360,208,1,375,1376,
81371,1882,3050,16,0,
8138208,1,377,1381,1,
8139379,1386,1,380,1391,
81401,883,3051,16,0,
8141208,1,373,1409,1,
8142130,3052,16,0,208,
81431,143,3053,16,0,
8144208,1,387,3054,16,
81450,208,1,2664,3055,
814616,0,208,1,1159,
81473056,16,0,208,1,
8148157,3057,16,0,208,
81491,1413,3058,16,0,
8150208,1,1665,3059,16,
81510,208,1,412,3060,
815216,0,208,1,1377,
81533061,16,0,208,1,
8154172,3062,16,0,208,
81551,1939,3063,16,0,
8156208,1,437,3064,16,
81570,208,1,188,3065,
815816,0,208,1,942,
81591490,1,1195,3066,16,
81600,208,1,1449,3067,
816116,0,208,1,1701,
81623068,16,0,208,1,
8163447,1511,1,205,3069,
816416,0,208,1,827,
81653070,16,0,208,1,
8166223,3071,16,0,208,
81671,476,1543,1,477,
81681549,1,1231,3072,16,
81690,208,1,479,1559,
81701,480,1564,1,1485,
81713073,16,0,208,1,
81721737,3074,16,0,208,
81731,242,3075,16,0,
8174208,1,478,1583,1,
81751001,1588,1,1002,1593,
81761,41,3076,19,172,
81771,41,3077,5,84,
81781,1011,1102,1,1012,
81793078,16,0,170,1,
81801013,1258,1,262,1119,
81811,1267,3079,16,0,
8182170,1,515,3080,16,
81830,170,1,1521,3081,
818416,0,170,1,525,
81851216,1,283,1172,1,
81862299,3082,16,0,170,
81871,42,3083,16,0,
8188170,1,40,1177,1,
818944,1183,1,47,1184,
81901,1303,3084,16,0,
8191170,1,1555,3085,16,
81920,170,1,50,1201,
81931,48,1190,1,49,
81941196,1,51,1206,1,
819563,1222,1,305,1211,
81961,66,1228,1,67,
81971233,1,68,1238,1,
819869,1243,1,70,1248,
81991,73,3086,16,0,
8200170,1,74,1253,1,
8201328,1302,1,1048,1344,
82021,82,3087,16,0,
8203170,1,1840,3088,16,
82040,170,1,1591,3089,
820516,0,170,1,1341,
82063090,16,0,170,1,
82071096,1312,1,93,1318,
82081,352,1349,1,107,
82093091,16,0,170,1,
82101114,1343,1,118,3092,
821116,0,170,1,1123,
82123093,16,0,170,1,
8213371,1365,1,1628,3094,
821416,0,170,1,375,
82151376,1,1882,3095,16,
82160,170,1,377,1381,
82171,379,1386,1,380,
82181391,1,883,3096,16,
82190,170,1,373,1409,
82201,130,3097,16,0,
8221170,1,143,3098,16,
82220,170,1,387,3099,
822316,0,170,1,2664,
82243100,16,0,170,1,
82251159,3101,16,0,170,
82261,157,3102,16,0,
8227170,1,1413,3103,16,
82280,170,1,1665,3104,
822916,0,170,1,412,
82303105,16,0,170,1,
82311377,3106,16,0,170,
82321,172,3107,16,0,
8233170,1,1939,3108,16,
82340,170,1,437,3109,
823516,0,170,1,188,
82363110,16,0,170,1,
8237942,1490,1,1195,3111,
823816,0,170,1,1449,
82393112,16,0,170,1,
82401701,3113,16,0,170,
82411,447,1511,1,205,
82423114,16,0,170,1,
8243827,3115,16,0,170,
82441,223,3116,16,0,
8245170,1,476,1543,1,
8246477,1549,1,1231,3117,
824716,0,170,1,479,
82481559,1,480,1564,1,
82491485,3118,16,0,170,
82501,1737,3119,16,0,
8251170,1,242,3120,16,
82520,170,1,478,1583,
82531,1001,1588,1,1002,
82541593,1,42,3121,19,
8255394,1,42,3122,5,
825638,1,1901,3123,16,
82570,392,1,2075,3124,
825816,0,392,1,1860,
8259821,1,1803,787,1,
82601804,3125,16,0,392,
82611,2413,3126,16,0,
8262392,1,2198,3127,16,
82630,392,1,1873,835,
82641,1657,894,1,1989,
8265916,1,1990,3128,16,
82660,392,1,1775,3129,
826716,0,392,1,32,
82683130,16,0,392,1,
82692105,814,1,2106,3131,
827016,0,392,1,2364,
8271827,1,2227,908,1,
82722337,3132,16,0,392,
82731,2021,718,1,2458,
8274876,1,2459,882,1,
82752462,889,1,2136,842,
82761,2464,899,1,2029,
8277725,1,2030,731,1,
82782031,736,1,2032,741,
82791,2033,746,1,2035,
8280752,1,2037,757,1,
82812039,762,1,1931,861,
82821,2041,768,1,2043,
8283774,1,2045,779,1,
82841574,799,1,1958,3133,
828516,0,392,1,43,
82863134,19,453,1,43,
82873135,5,25,1,2035,
8288752,1,2037,757,1,
82892039,762,1,2041,768,
82901,2227,908,1,2043,
8291774,1,1657,894,1,
82921860,821,1,2136,842,
82931,2021,718,1,2459,
8294882,1,1574,799,1,
82952105,3136,16,0,578,
82961,1931,861,1,1873,
8297835,1,2031,736,1,
82981803,787,1,1989,3137,
829916,0,451,1,2464,
8300899,1,2029,725,1,
83012030,731,1,2364,827,
83021,2032,741,1,2033,
8303746,1,2045,779,1,
830444,3138,19,264,1,
830544,3139,5,38,1,
83061901,3140,16,0,262,
83071,2075,3141,16,0,
8308262,1,1860,821,1,
83091803,787,1,1804,3142,
831016,0,262,1,2413,
83113143,16,0,262,1,
83122198,3144,16,0,262,
83131,1873,835,1,1657,
8314894,1,1989,916,1,
83151990,3145,16,0,262,
83161,1775,3146,16,0,
8317262,1,32,3147,16,
83180,262,1,2105,814,
83191,2106,3148,16,0,
8320262,1,2364,827,1,
83212227,908,1,2337,3149,
832216,0,262,1,2021,
8323718,1,2458,876,1,
83242459,882,1,2462,889,
83251,2136,842,1,2464,
8326899,1,2029,725,1,
83272030,731,1,2031,736,
83281,2032,741,1,2033,
8329746,1,2035,752,1,
83302037,757,1,2039,762,
83311,1931,861,1,2041,
8332768,1,2043,774,1,
83332045,779,1,1574,799,
83341,1958,3150,16,0,
8335262,1,45,3151,19,
8336287,1,45,3152,5,
833739,1,1901,3153,16,
83380,315,1,2075,3154,
833916,0,315,1,1860,
8340821,1,1803,787,1,
83411804,3155,16,0,315,
83421,2413,3156,16,0,
8343315,1,2198,3157,16,
83440,315,1,1873,835,
83451,1657,894,1,1989,
8346916,1,1990,3158,16,
83470,315,1,1775,3159,
834816,0,315,1,32,
83493160,16,0,315,1,
83502105,814,1,2106,3161,
835116,0,315,1,2364,
8352827,1,2227,908,1,
83532337,3162,16,0,315,
83541,2021,718,1,2458,
8355876,1,2459,882,1,
83562462,889,1,2136,842,
83571,2464,899,1,2029,
8358725,1,2030,731,1,
83592031,736,1,2032,741,
83601,2033,746,1,2035,
8361752,1,2037,757,1,
83622039,762,1,1931,861,
83631,2041,768,1,2043,
8364774,1,2045,779,1,
83651832,3163,16,0,285,
83661,1574,799,1,1958,
83673164,16,0,315,1,
836846,3165,19,671,1,
836946,3166,5,38,1,
83701901,3167,16,0,669,
83711,2075,3168,16,0,
8372669,1,1860,821,1,
83731803,787,1,1804,3169,
837416,0,669,1,2413,
83753170,16,0,669,1,
83762198,3171,16,0,669,
83771,1873,835,1,1657,
8378894,1,1989,916,1,
83791990,3172,16,0,669,
83801,1775,3173,16,0,
8381669,1,32,3174,16,
83820,669,1,2105,814,
83831,2106,3175,16,0,
8384669,1,2364,827,1,
83852227,908,1,2337,3176,
838616,0,669,1,2021,
8387718,1,2458,876,1,
83882459,882,1,2462,889,
83891,2136,842,1,2464,
8390899,1,2029,725,1,
83912030,731,1,2031,736,
83921,2032,741,1,2033,
8393746,1,2035,752,1,
83942037,757,1,2039,762,
83951,1931,861,1,2041,
8396768,1,2043,774,1,
83972045,779,1,1574,799,
83981,1958,3177,16,0,
8399669,1,47,3178,19,
8400466,1,47,3179,5,
840119,1,0,3180,16,
84020,464,1,2706,3181,
840316,0,464,1,2634,
8404691,1,2636,3182,16,
84050,464,1,2639,707,
84061,2714,3183,17,3184,
840715,3185,4,36,37,
84080,71,0,108,0,
8409111,0,98,0,97,
84100,108,0,68,0,
8411101,0,102,0,105,
84120,110,0,105,0,
8413116,0,105,0,111,
84140,110,0,115,0,
84151,-1,1,5,3186,
841620,3187,4,38,71,
84170,108,0,111,0,
841898,0,97,0,108,
84190,68,0,101,0, 75400,68,0,101,0,
8420102,0,105,0,110, 754199,0,108,0,97,
84210,105,0,116,0, 75420,114,0,97,0,
7543116,0,105,0,111,
75440,110,0,76,0,
7545105,0,115,0,116,
75460,1,-1,1,5,
75472278,20,2279,4,68,
754873,0,110,0,116,
75490,86,0,101,0,
755099,0,86,0,101,
75510,99,0,65,0,
7552114,0,103,0,117,
75530,109,0,101,0,
7554110,0,116,0,68,
75550,101,0,99,0,
7556108,0,97,0,114,
75570,97,0,116,0,
8422105,0,111,0,110, 7558105,0,111,0,110,
84230,115,0,95,0, 75590,76,0,105,0,
842450,0,1,145,1, 7560115,0,116,0,95,
84253,1,3,1,2, 75610,49,0,1,210,
84263188,22,1,4,1, 75621,3,1,6,1,
84272558,697,1,2716,3189, 75635,2280,22,1,46,
842817,3190,15,3185,1, 75641,2281,1276,1,525,
8429-1,1,5,3191,20, 75651339,1,30,1904,1,
84303192,4,38,71,0, 75661002,1715,1,283,1295,
8431108,0,111,0,98, 75671,2546,2281,17,2282,
84320,97,0,108,0, 756815,2283,4,66,37,
843368,0,101,0,102, 75690,73,0,110,0,
84340,105,0,110,0, 7570116,0,82,0,111,
8435105,0,116,0,105, 75710,116,0,82,0,
7572111,0,116,0,65,
75730,114,0,103,0,
7574117,0,109,0,101,
75750,110,0,116,0,
757668,0,101,0,99,
75770,108,0,97,0,
7578114,0,97,0,116,
75790,105,0,111,0,
7580110,0,76,0,105,
75810,115,0,116,0,
75821,-1,1,5,2284,
758320,2285,4,68,73,
75840,110,0,116,0,
758582,0,111,0,116,
75860,82,0,111,0,
7587116,0,65,0,114,
75880,103,0,117,0,
7589109,0,101,0,110,
75900,116,0,68,0,
7591101,0,99,0,108,
75920,97,0,114,0,
759397,0,116,0,105,
84360,111,0,110,0, 75940,111,0,110,0,
8437115,0,95,0,49, 759576,0,105,0,115,
84380,1,144,1,3, 75960,116,0,95,0,
84391,2,1,1,3193, 759749,0,1,209,1,
844022,1,3,1,2022, 75983,1,6,1,5,
84413194,16,0,567,1, 75992286,22,1,45,1,
84422459,882,1,2715,3195, 76002547,2287,16,0,519,
844317,3196,15,3185,1, 76011,1010,2288,16,0,
8444-1,1,5,3197,20, 7602701,1,40,1300,1,
84453198,4,38,71,0, 760341,1916,1,42,1920,
8446108,0,111,0,98, 76041,44,1306,1,2555,
84470,97,0,108,0, 76052289,16,0,645,1,
844868,0,101,0,102, 76061260,1218,1,47,1307,
84490,105,0,110,0, 76071,48,1313,1,49,
8450105,0,116,0,105, 76081319,1,50,1324,1,
760951,1329,1,2562,2290,
761017,2291,15,2292,4,
761154,37,0,73,0,
7612110,0,116,0,65,
76130,114,0,103,0,
7614117,0,109,0,101,
76150,110,0,116,0,
761668,0,101,0,99,
76170,108,0,97,0,
7618114,0,97,0,116,
76190,105,0,111,0,
7620110,0,76,0,105,
76210,115,0,116,0,
76221,-1,1,5,2293,
762320,2294,4,56,73,
76240,110,0,116,0,
762565,0,114,0,103,
76260,117,0,109,0,
7627101,0,110,0,116,
76280,68,0,101,0,
762999,0,108,0,97,
76300,114,0,97,0,
7631116,0,105,0,111,
76320,110,0,76,0,
7633105,0,115,0,116,
76340,95,0,49,0,
76351,207,1,3,1,
76362,1,1,2295,22,
76371,43,1,2563,2296,
763816,0,661,1,305,
76391334,1,2576,2297,16,
76400,571,1,2570,2298,
764117,2299,15,2300,4,
764254,37,0,75,0,
7643101,0,121,0,65,
76440,114,0,103,0,
7645117,0,109,0,101,
76460,110,0,116,0,
764768,0,101,0,99,
76480,108,0,97,0,
7649114,0,97,0,116,
76500,105,0,111,0,
7651110,0,76,0,105,
76520,115,0,116,0,
76531,-1,1,5,2301,
765420,2302,4,56,75,
76550,101,0,121,0,
765665,0,114,0,103,
76570,117,0,109,0,
7658101,0,110,0,116,
76590,68,0,101,0,
766099,0,108,0,97,
76610,114,0,97,0,
7662116,0,105,0,111,
76630,110,0,76,0,
7664105,0,115,0,116,
76650,95,0,49,0,
76661,206,1,3,1,
76672,1,1,2303,22,
76681,42,1,61,2304,
766916,0,220,1,63,
76701345,1,66,1351,1,
767167,1356,1,68,1361,
76721,69,1366,1,70,
76731371,1,2581,1926,1,
767473,2305,16,0,230,
76751,74,1376,1,1013,
76761381,1,2335,2306,16,
76770,266,1,1332,1386,
76781,1048,1462,1,2590,
76792307,16,0,774,1,
768082,1403,1,1840,2308,
768116,0,338,1,2516,
76822309,17,2310,15,2311,
76834,66,37,0,75,
76840,101,0,121,0,
768573,0,110,0,116,
76860,73,0,110,0,
7687116,0,65,0,114,
76880,103,0,117,0,
7689109,0,101,0,110,
76900,116,0,68,0,
7691101,0,99,0,108,
76920,97,0,114,0,
769397,0,116,0,105,
84510,111,0,110,0, 76940,111,0,110,0,
8452115,0,95,0,51, 769576,0,105,0,115,
84530,1,146,1,3, 76960,116,0,1,-1,
84541,2,1,1,3199, 76971,5,2312,20,2313,
845522,1,5,1,2464, 76984,68,75,0,101,
8456899,1,2466,3200,17, 76990,121,0,73,0,
84573201,15,3202,4,50, 7700110,0,116,0,73,
77010,110,0,116,0,
770265,0,114,0,103,
77030,117,0,109,0,
7704101,0,110,0,116,
77050,68,0,101,0,
770699,0,108,0,97,
77070,114,0,97,0,
7708116,0,105,0,111,
77090,110,0,76,0,
7710105,0,115,0,116,
77110,95,0,49,0,
77121,211,1,3,1,
77136,1,5,2314,22,
77141,47,1,2517,2315,
771516,0,487,1,328,
77161425,1,1303,1430,1,
77171096,1694,1,93,1435,
77181,1550,1440,1,827,
77191448,1,2532,2316,16,
77200,628,1,1011,1224,
77211,107,1455,1,1114,
77221461,1,2542,1909,1,
77231871,2317,16,0,348,
77241,1370,1570,1,1478,
77251575,1,118,1473,1,
77261123,1478,1,371,1483,
77271,1377,1489,1,375,
77281494,1,1882,2318,16,
77290,363,1,377,1499,
77301,352,1467,1,379,
77311504,1,1341,1420,1,
7732130,1532,1,2074,2319,
773316,0,641,1,373,
77341527,1,1012,2320,16,
77350,703,1,380,1509,
77361,143,1537,1,1152,
77371543,1,1406,1548,1,
77381159,1555,1,157,1560,
77391,1413,1565,1,883,
77401515,1,2512,1882,1,
77411296,1290,1,172,1586,
77421,1665,1591,1,2766,
77431934,1,1939,2321,16,
77440,482,1,1188,1596,
77451,1442,1601,1,188,
77461635,1,942,1607,1,
77471195,1613,1,1449,1618,
77481,1701,1623,1,447,
77491628,1,1094,2322,16,
77500,785,1,205,1640,
77511,2554,2323,17,2324,
775215,2325,4,60,37,
77530,86,0,101,0,
775499,0,116,0,111,
77550,114,0,65,0,
7756114,0,103,0,117,
77570,109,0,101,0,
7758110,0,116,0,68,
77590,101,0,99,0,
7760108,0,97,0,114,
77610,97,0,116,0,
7762105,0,111,0,110,
77630,76,0,105,0,
7764115,0,116,0,1,
7765-1,1,5,2326,20,
77662327,4,62,86,0,
7767101,0,99,0,116,
77680,111,0,114,0,
776965,0,114,0,103,
77700,117,0,109,0,
7771101,0,110,0,116,
77720,68,0,101,0,
777399,0,108,0,97,
77740,114,0,97,0,
7775116,0,105,0,111,
77760,110,0,76,0,
7777105,0,115,0,116,
77780,95,0,49,0,
77791,208,1,3,1,
77802,1,1,2328,22,
77811,44,1,2467,1938,
77821,464,1944,1,2197,
77832329,16,0,772,1,
77841224,1645,1,223,1650,
77851,1730,1655,1,2571,
77862330,16,0,673,1,
7787477,1666,1,1231,1671,
77881,479,1676,1,480,
77891681,1,1485,1687,1,
7790459,1949,1,476,1660,
77911,242,1700,1,478,
77921705,1,481,1951,1,
77931001,1710,1,2508,1956,
77941,18,2331,19,564,
77951,18,2332,5,84,
77961,1011,1224,1,1012,
77972333,16,0,562,1,
77981013,1381,1,262,1241,
77991,1267,2334,16,0,
7800562,1,515,2335,16,
78010,562,1,1521,2336,
780216,0,562,1,525,
78031339,1,2788,2337,16,
78040,562,1,283,1295,
78051,2299,2338,16,0,
7806562,1,42,2339,16,
78070,562,1,40,1300,
78081,44,1306,1,47,
78091307,1,1303,2340,16,
78100,562,1,1555,2341,
781116,0,562,1,50,
78121324,1,48,1313,1,
781349,1319,1,51,1329,
78141,63,1345,1,305,
78151334,1,66,1351,1,
781667,1356,1,68,1361,
78171,69,1366,1,70,
78181371,1,73,2342,16,
78190,562,1,74,1376,
78201,328,1425,1,1048,
78212343,16,0,562,1,
782282,2344,16,0,562,
78231,1840,2345,16,0,
7824562,1,1591,2346,16,
78250,562,1,1341,2347,
782616,0,562,1,1096,
78271694,1,93,1435,1,
7828352,1467,1,107,2348,
782916,0,562,1,1114,
78301461,1,118,2349,16,
78310,562,1,1123,2350,
783216,0,562,1,371,
78331483,1,1628,2351,16,
78340,562,1,375,1494,
78351,1882,2352,16,0,
7836562,1,377,1499,1,
7837379,1504,1,380,1509,
78381,883,2353,16,0,
7839562,1,373,1527,1,
7840130,2354,16,0,562,
78411,143,2355,16,0,
7842562,1,387,2356,16,
78430,562,1,1159,2357,
784416,0,562,1,157,
78452358,16,0,562,1,
78461413,2359,16,0,562,
78471,1665,2360,16,0,
7848562,1,412,2361,16,
78490,562,1,1377,2362,
785016,0,562,1,172,
78512363,16,0,562,1,
78521939,2364,16,0,562,
78531,437,2365,16,0,
7854562,1,188,2366,16,
78550,562,1,942,2367,
785616,0,562,1,1195,
78572368,16,0,562,1,
78581449,2369,16,0,562,
78591,1701,2370,16,0,
7860562,1,447,1628,1,
7861205,2371,16,0,562,
78621,827,2372,16,0,
7863562,1,223,2373,16,
78640,562,1,476,1660,
78651,477,1666,1,1231,
78662374,16,0,562,1,
7867479,1676,1,480,1681,
78681,1485,2375,16,0,
7869562,1,1737,2376,16,
78700,562,1,242,2377,
787116,0,562,1,478,
78721705,1,1001,1710,1,
78731002,1715,1,19,2378,
787419,254,1,19,2379,
78755,176,1,256,2380,
787616,0,252,1,1261,
78772381,16,0,252,1,
78781011,1224,1,1012,2382,
787916,0,521,1,2458,
7880998,1,262,1241,1,
78811267,2383,16,0,521,
78821,2021,840,1,1521,
78832384,16,0,521,1,
78841775,2385,16,0,252,
78851,2029,847,1,2030,
7886853,1,2031,858,1,
78872032,863,1,2033,868,
78881,277,2386,16,0,
7889252,1,2788,2387,16,
78900,521,1,2037,879,
78911,2039,884,1,32,
78922388,16,0,252,1,
78932464,1021,1,2293,2389,
789416,0,252,1,2043,
7895896,1,2045,901,1,
78962299,2390,16,0,521,
78971,41,2391,16,0,
7898252,1,42,2392,16,
78990,521,1,40,1300,
79001,44,1306,1,43,
79012393,16,0,252,1,
79021804,2394,16,0,252,
79031,48,1313,1,49,
79041319,1,47,1307,1,
790551,1329,1,52,2395,
790616,0,252,1,50,
79071324,1,305,1334,1,
79081096,1694,1,1515,2396,
790916,0,252,1,2318,
79102397,16,0,252,1,
7911283,1295,1,63,1345,
79121,66,1351,1,67,
79131356,1,68,1361,1,
791469,1366,1,70,1371,
79151,71,2398,16,0,
7916252,1,73,2399,16,
79170,521,1,74,1376,
79181,1013,1381,1,76,
79192400,16,0,252,1,
79201834,2401,16,0,252,
79211,2337,2402,16,0,
7922252,1,79,2403,16,
79230,252,1,1335,2404,
792416,0,252,1,299,
79252405,16,0,252,1,
792682,2406,16,0,521,
79271,1840,2407,16,0,
7928521,1,1297,2408,16,
79290,252,1,85,2409,
793016,0,252,1,1341,
79312410,16,0,521,1,
793289,2411,16,0,252,
79331,1303,2412,16,0,
7934521,1,2035,874,1,
793593,1435,1,322,2413,
793616,0,252,1,97,
79372414,16,0,252,1,
79382041,890,1,1555,2415,
793916,0,521,1,827,
79402416,16,0,521,1,
7941102,2417,16,0,252,
79421,1860,943,1,1803,
7943909,1,2364,949,1,
7944107,2418,16,0,521,
79451,509,2419,16,0,
7946252,1,1114,1461,1,
7947112,2420,16,0,252,
79481,1117,2421,16,0,
7949252,1,352,1467,1,
79501873,958,1,118,2422,
795116,0,521,1,1123,
79522423,16,0,521,1,
7953371,1483,1,515,2424,
795416,0,521,1,1377,
79552425,16,0,521,1,
7956124,2426,16,0,252,
79571,1882,2427,16,0,
7958521,1,377,1499,1,
7959379,1504,1,380,1509,
79601,130,2428,16,0,
7961521,1,346,2429,16,
79620,252,1,2075,2430,
796316,0,252,1,373,
79641527,1,387,2431,16,
79650,521,1,137,2432,
796616,0,252,1,143,
79672433,16,0,521,1,
79681901,2434,16,0,252,
79691,1048,2435,16,0,
7970521,1,1153,2436,16,
79710,252,1,375,1494,
79721,151,2437,16,0,
7973252,1,1407,2438,16,
79740,252,1,1659,2439,
797516,0,252,1,2413,
79762440,16,0,252,1,
79771159,2441,16,0,521,
79781,381,2442,16,0,
7979252,1,157,2443,16,
79800,521,1,1413,2444,
798116,0,521,1,883,
79822445,16,0,521,1,
79831371,2446,16,0,252,
79841,328,1425,1,2105,
7985936,1,2106,2447,16,
79860,252,1,166,2448,
798716,0,252,1,525,
79882449,16,0,252,1,
79891622,2450,16,0,252,
79901,406,2451,16,0,
7991252,1,1574,921,1,
7992172,2452,16,0,521,
79931,1931,983,1,412,
79942453,16,0,521,1,
79951933,2454,16,0,252,
79961,1876,2455,16,0,
7997252,1,431,2456,16,
79980,252,1,1585,2457,
799916,0,252,1,182,
80002458,16,0,252,1,
80011628,2459,16,0,521,
80021,1189,2460,16,0,
8003252,1,437,2461,16,
80040,521,1,1591,2462,
800516,0,521,1,188,
80062463,16,0,521,1,
80071695,2464,16,0,252,
80081,2198,2465,16,0,
8009252,1,1195,2466,16,
80100,521,1,1449,2467,
801116,0,521,1,1701,
80122468,16,0,521,1,
8013447,2469,16,0,252,
80141,2782,2470,16,0,
8015252,1,199,2471,16,
80160,252,1,2459,1004,
80171,1958,2472,16,0,
8018252,1,2462,1011,1,
80191657,1016,1,205,2473,
802016,0,521,1,459,
80212474,16,0,252,1,
8022462,2475,16,0,252,
80231,1665,2476,16,0,
8024521,1,217,2477,16,
80250,252,1,2227,1030,
80261,942,2478,16,0,
8027521,1,1225,2479,16,
80280,252,1,223,2480,
802916,0,521,1,1479,
80302481,16,0,252,1,
80311731,2482,16,0,252,
80321,477,1666,1,1231,
80332483,16,0,521,1,
8034479,1676,1,480,1681,
80351,1485,2484,16,0,
8036521,1,1737,2485,16,
80370,521,1,1989,1038,
80381,1990,2486,16,0,
8039252,1,1443,2487,16,
80400,252,1,236,2488,
804116,0,252,1,2136,
8042965,1,476,1660,1,
8043242,2489,16,0,521,
80441,478,1705,1,1939,
80452490,16,0,521,1,
80461001,1710,1,1002,1715,
80471,1756,2491,16,0,
8048252,1,20,2492,19,
8049496,1,20,2493,5,
805084,1,1011,1224,1,
80511012,2494,16,0,494,
80521,1013,1381,1,262,
80531241,1,1267,2495,16,
80540,494,1,515,2496,
805516,0,494,1,1521,
80562497,16,0,494,1,
8057525,1339,1,2788,2498,
805816,0,494,1,283,
80591295,1,2299,2499,16,
80600,494,1,42,2500,
806116,0,494,1,40,
80621300,1,44,1306,1,
806347,1307,1,1303,2501,
806416,0,494,1,1555,
80652502,16,0,494,1,
806650,1324,1,48,1313,
80671,49,1319,1,51,
80681329,1,63,1345,1,
8069305,1334,1,66,1351,
80701,67,1356,1,68,
80711361,1,69,1366,1,
807270,1371,1,73,2503,
807316,0,494,1,74,
80741376,1,328,2504,16,
80750,494,1,1048,2505,
807616,0,494,1,82,
80772506,16,0,494,1,
80781840,2507,16,0,494,
80791,1591,2508,16,0,
8080494,1,1341,2509,16,
80810,494,1,1096,1694,
80821,93,1435,1,352,
80832510,16,0,494,1,
8084107,2511,16,0,494,
80851,1114,1461,1,118,
80862512,16,0,494,1,
80871123,2513,16,0,494,
80881,371,1483,1,1628,
80892514,16,0,494,1,
8090375,1494,1,1882,2515,
809116,0,494,1,377,
80921499,1,379,1504,1,
8093380,1509,1,883,2516,
809416,0,494,1,373,
80951527,1,130,2517,16,
80960,494,1,143,2518,
809716,0,494,1,387,
80982519,16,0,494,1,
80991159,2520,16,0,494,
81001,157,2521,16,0,
8101494,1,1413,2522,16,
81020,494,1,1665,2523,
810316,0,494,1,412,
81042524,16,0,494,1,
81051377,2525,16,0,494,
81061,172,2526,16,0,
8107494,1,1939,2527,16,
81080,494,1,437,2528,
810916,0,494,1,188,
81102529,16,0,494,1,
8111942,2530,16,0,494,
81121,1195,2531,16,0,
8113494,1,1449,2532,16,
81140,494,1,1701,2533,
811516,0,494,1,447,
81161628,1,205,2534,16,
81170,494,1,827,2535,
811816,0,494,1,223,
81192536,16,0,494,1,
8120476,1660,1,477,1666,
81211,1231,2537,16,0,
8122494,1,479,1676,1,
8123480,1681,1,1485,2538,
812416,0,494,1,1737,
81252539,16,0,494,1,
8126242,2540,16,0,494,
81271,478,1705,1,1001,
81281710,1,1002,1715,1,
812921,2541,19,468,1,
813021,2542,5,84,1,
81311011,1224,1,1012,2543,
813216,0,466,1,1013,
81331381,1,262,1241,1,
81341267,2544,16,0,466,
81351,515,2545,16,0,
8136466,1,1521,2546,16,
81370,466,1,525,1339,
81381,2788,2547,16,0,
8139466,1,283,1295,1,
81402299,2548,16,0,466,
81411,42,2549,16,0,
8142466,1,40,1300,1,
814344,1306,1,47,1307,
81441,1303,2550,16,0,
8145466,1,1555,2551,16,
81460,466,1,50,1324,
81471,48,1313,1,49,
81481319,1,51,1329,1,
814963,1345,1,305,1334,
81501,66,1351,1,67,
81511356,1,68,1361,1,
815269,1366,1,70,1371,
81531,73,2552,16,0,
8154466,1,74,1376,1,
8155328,2553,16,0,466,
81561,1048,2554,16,0,
8157466,1,82,2555,16,
81580,466,1,1840,2556,
815916,0,466,1,1591,
81602557,16,0,466,1,
81611341,2558,16,0,466,
81621,1096,1694,1,93,
81631435,1,352,2559,16,
81640,466,1,107,2560,
816516,0,466,1,1114,
81661461,1,118,2561,16,
81670,466,1,1123,2562,
816816,0,466,1,371,
81691483,1,1628,2563,16,
81700,466,1,375,1494,
81711,1882,2564,16,0,
8172466,1,377,1499,1,
8173379,1504,1,380,1509,
81741,883,2565,16,0,
8175466,1,373,1527,1,
8176130,2566,16,0,466,
81771,143,2567,16,0,
8178466,1,387,2568,16,
81790,466,1,1159,2569,
818016,0,466,1,157,
81812570,16,0,466,1,
81821413,2571,16,0,466,
81831,1665,2572,16,0,
8184466,1,412,2573,16,
81850,466,1,1377,2574,
818616,0,466,1,172,
81872575,16,0,466,1,
81881939,2576,16,0,466,
81891,437,2577,16,0,
8190466,1,188,2578,16,
81910,466,1,942,2579,
819216,0,466,1,1195,
81932580,16,0,466,1,
81941449,2581,16,0,466,
81951,1701,2582,16,0,
8196466,1,447,1628,1,
8197205,2583,16,0,466,
81981,827,2584,16,0,
8199466,1,223,2585,16,
82000,466,1,476,1660,
82011,477,1666,1,1231,
82022586,16,0,466,1,
8203479,1676,1,480,1681,
82041,1485,2587,16,0,
8205466,1,1737,2588,16,
82060,466,1,242,2589,
820716,0,466,1,478,
82081705,1,1001,1710,1,
82091002,1715,1,22,2590,
821019,419,1,22,2591,
82115,84,1,1011,1224,
82121,1012,2592,16,0,
8213417,1,1013,1381,1,
8214262,1241,1,1267,2593,
821516,0,417,1,515,
82162594,16,0,417,1,
82171521,2595,16,0,417,
82181,525,1339,1,2788,
82192596,16,0,417,1,
8220283,1295,1,2299,2597,
822116,0,417,1,42,
82222598,16,0,417,1,
822340,1300,1,44,1306,
82241,47,1307,1,1303,
82252599,16,0,417,1,
82261555,2600,16,0,417,
82271,50,1324,1,48,
82281313,1,49,1319,1,
822951,1329,1,63,1345,
82301,305,1334,1,66,
82311351,1,67,1356,1,
823268,1361,1,69,1366,
82331,70,1371,1,73,
82342601,16,0,417,1,
823574,1376,1,328,2602,
823616,0,417,1,1048,
82372603,16,0,417,1,
823882,2604,16,0,417,
82391,1840,2605,16,0,
8240417,1,1591,2606,16,
82410,417,1,1341,2607,
824216,0,417,1,1096,
82431694,1,93,1435,1,
8244352,2608,16,0,417,
82451,107,2609,16,0,
8246417,1,1114,1461,1,
8247118,2610,16,0,417,
82481,1123,2611,16,0,
8249417,1,371,1483,1,
82501628,2612,16,0,417,
82511,375,1494,1,1882,
82522613,16,0,417,1,
8253377,1499,1,379,1504,
82541,380,1509,1,883,
82552614,16,0,417,1,
8256373,1527,1,130,2615,
825716,0,417,1,143,
82582616,16,0,417,1,
8259387,2617,16,0,417,
82601,1159,2618,16,0,
8261417,1,157,2619,16,
82620,417,1,1413,2620,
826316,0,417,1,1665,
82642621,16,0,417,1,
8265412,2622,16,0,417,
82661,1377,2623,16,0,
8267417,1,172,2624,16,
82680,417,1,1939,2625,
826916,0,417,1,437,
82702626,16,0,417,1,
8271188,2627,16,0,417,
82721,942,2628,16,0,
8273417,1,1195,2629,16,
82740,417,1,1449,2630,
827516,0,417,1,1701,
82762631,16,0,417,1,
8277447,1628,1,205,2632,
827816,0,417,1,827,
82792633,16,0,417,1,
8280223,2634,16,0,417,
82811,476,1660,1,477,
82821666,1,1231,2635,16,
82830,417,1,479,1676,
82841,480,1681,1,1485,
82852636,16,0,417,1,
82861737,2637,16,0,417,
82871,242,2638,16,0,
8288417,1,478,1705,1,
82891001,1710,1,1002,1715,
82901,23,2639,19,582,
82911,23,2640,5,38,
82921,1901,2641,16,0,
8293580,1,2075,2642,16,
82940,580,1,1860,943,
82951,1803,909,1,1804,
82962643,16,0,580,1,
82972413,2644,16,0,580,
82981,2198,2645,16,0,
8299580,1,1873,958,1,
83001657,1016,1,1989,1038,
83011,1990,2646,16,0,
8302580,1,1775,2647,16,
83030,580,1,32,2648,
830416,0,580,1,2105,
8305936,1,2106,2649,16,
83060,580,1,2364,949,
83071,2227,1030,1,2337,
83082650,16,0,580,1,
83092021,840,1,2458,998,
83101,2459,1004,1,2462,
83111011,1,2136,965,1,
83122464,1021,1,2029,847,
83131,2030,853,1,2031,
8314858,1,2032,863,1,
83152033,868,1,2035,874,
83161,2037,879,1,2039,
8317884,1,1931,983,1,
83182041,890,1,2043,896,
83191,2045,901,1,1574,
8320921,1,1958,2651,16,
83210,580,1,24,2652,
832219,196,1,24,2653,
83235,5,1,44,2654,
832416,0,194,1,377,
83252655,16,0,618,1,
832640,2656,16,0,796,
83271,63,2657,16,0,
8328222,1,373,2658,16,
83290,614,1,25,2659,
833019,324,1,25,2660,
83315,177,1,256,2661,
833216,0,623,1,1261,
83332662,16,0,623,1,
83341011,1224,1,1012,2663,
833516,0,322,1,2458,
8336998,1,262,1241,1,
83371267,2664,16,0,322,
83381,2021,840,1,1521,
83392665,16,0,322,1,
83401775,2666,16,0,623,
83411,2029,847,1,2030,
8342853,1,2031,858,1,
83432032,863,1,2033,868,
83441,277,2667,16,0,
8345623,1,2788,2668,16,
83460,322,1,2037,879,
83471,2039,884,1,32,
83482669,16,0,623,1,
83492464,1021,1,2293,2670,
835016,0,623,1,2043,
8351896,1,2045,901,1,
83522299,2671,16,0,322,
83531,41,2672,16,0,
8354623,1,42,2673,16,
83550,322,1,40,1300,
83561,44,1306,1,43,
83572674,16,0,623,1,
83581804,2675,16,0,623,
83591,48,1313,1,49,
83601319,1,47,1307,1,
836151,1329,1,52,2676,
836216,0,623,1,50,
83631324,1,305,1334,1,
83641096,1694,1,1515,2677,
836516,0,623,1,2318,
83662678,16,0,623,1,
836762,2679,16,0,623,
83681,63,1345,1,66,
83691351,1,67,1356,1,
837068,1361,1,69,1366,
83711,70,1371,1,71,
83722680,16,0,623,1,
8373283,1295,1,73,2681,
837416,0,322,1,74,
83751376,1,1013,1381,1,
837676,2682,16,0,623,
83771,1834,2683,16,0,
8378623,1,2337,2684,16,
83790,623,1,79,2685,
838016,0,623,1,1335,
83812686,16,0,623,1,
8382299,2687,16,0,623,
83831,82,2688,16,0,
8384322,1,1840,2689,16,
83850,322,1,1297,2690,
838616,0,623,1,85,
83872691,16,0,623,1,
83881341,2692,16,0,322,
83891,89,2693,16,0,
8390623,1,1303,2694,16,
83910,322,1,2035,874,
83921,93,1435,1,322,
83932695,16,0,623,1,
839497,2696,16,0,623,
83951,2041,890,1,1555,
83962697,16,0,322,1,
8397827,2698,16,0,322,
83981,102,2699,16,0,
8399623,1,1860,943,1,
84001803,909,1,2364,949,
84011,107,2700,16,0,
8402322,1,509,2701,16,
84030,623,1,1114,1461,
84041,112,2702,16,0,
8405623,1,1117,2703,16,
84060,623,1,352,1467,
84071,1873,958,1,118,
84081473,1,1123,2704,16,
84090,322,1,371,1483,
84101,515,2705,16,0,
8411322,1,1377,2706,16,
84120,322,1,124,2707,
841316,0,623,1,1882,
84142708,16,0,322,1,
8415377,1499,1,379,1504,
84161,380,1509,1,130,
84171532,1,346,2709,16,
84180,623,1,2075,2710,
841916,0,623,1,373,
84201527,1,387,2711,16,
84210,322,1,137,2712,
842216,0,623,1,143,
84232713,16,0,322,1,
84241901,2714,16,0,623,
84251,1048,1462,1,1153,
84262715,16,0,623,1,
8427375,1494,1,151,2716,
842816,0,623,1,1407,
84292717,16,0,623,1,
84301659,2718,16,0,623,
84311,2413,2719,16,0,
8432623,1,1159,2720,16,
84330,322,1,381,2721,
843416,0,623,1,157,
84352722,16,0,322,1,
84361413,2723,16,0,322,
84371,883,2724,16,0,
8438322,1,1371,2725,16,
84390,623,1,328,1425,
84401,2105,936,1,2106,
84412726,16,0,623,1,
8442166,2727,16,0,623,
84431,525,2728,16,0,
8444623,1,1622,2729,16,
84450,623,1,406,2730,
844616,0,623,1,1574,
8447921,1,172,1586,1,
84481931,983,1,412,2731,
844916,0,322,1,1933,
84502732,16,0,623,1,
84511876,2733,16,0,623,
84521,431,2734,16,0,
8453623,1,1585,2735,16,
84540,623,1,182,2736,
845516,0,623,1,1628,
84562737,16,0,322,1,
84571189,2738,16,0,623,
84581,437,2739,16,0,
8459322,1,1591,2740,16,
84600,322,1,188,1635,
84611,1695,2741,16,0,
8462623,1,2198,2742,16,
84630,623,1,1195,2743,
846416,0,322,1,1449,
84652744,16,0,322,1,
84661701,2745,16,0,322,
84671,447,2746,16,0,
8468623,1,2782,2747,16,
84690,623,1,199,2748,
847016,0,623,1,2459,
84711004,1,1958,2749,16,
84720,623,1,2462,1011,
84731,1657,1016,1,205,
84742750,16,0,322,1,
8475459,2751,16,0,623,
84761,462,2752,16,0,
8477623,1,1665,2753,16,
84780,322,1,217,2754,
847916,0,623,1,2227,
84801030,1,942,1607,1,
84811225,2755,16,0,623,
84821,223,2756,16,0,
8483322,1,1479,2757,16,
84840,623,1,1731,2758,
848516,0,623,1,477,
84861666,1,1231,2759,16,
84870,322,1,479,1676,
84881,480,1681,1,1485,
84892760,16,0,322,1,
84901737,2761,16,0,322,
84911,1989,1038,1,1990,
84922762,16,0,623,1,
84931443,2763,16,0,623,
84941,236,2764,16,0,
8495623,1,2136,965,1,
8496476,1660,1,242,2765,
849716,0,322,1,478,
84981705,1,1939,2766,16,
84990,322,1,1001,1710,
85001,1002,1715,1,1756,
85012767,16,0,623,1,
850226,2768,19,343,1,
850326,2769,5,84,1,
85041011,1224,1,1012,2770,
850516,0,341,1,1013,
85061381,1,262,1241,1,
85071267,2771,16,0,341,
85081,515,2772,16,0,
8509770,1,1521,2773,16,
85100,341,1,525,1339,
85111,2788,2774,16,0,
8512341,1,283,1295,1,
85132299,2775,16,0,341,
85141,42,2776,16,0,
8515341,1,40,1300,1,
851644,1306,1,47,1307,
85171,1303,2777,16,0,
8518341,1,1555,2778,16,
85190,341,1,50,1324,
85201,48,1313,1,49,
85211319,1,51,1329,1,
852263,1345,1,305,1334,
85231,66,1351,1,67,
85241356,1,68,1361,1,
852569,1366,1,70,1371,
85261,73,2779,16,0,
8527341,1,74,1376,1,
8528328,1425,1,1048,1462,
85291,82,2780,16,0,
8530341,1,1840,2781,16,
85310,341,1,1591,2782,
853216,0,341,1,1341,
85332783,16,0,341,1,
85341096,1694,1,93,1435,
85351,352,1467,1,107,
85362784,16,0,341,1,
85371114,1461,1,118,1473,
85381,1123,2785,16,0,
8539341,1,371,1483,1,
85401628,2786,16,0,341,
85411,375,1494,1,1882,
85422787,16,0,341,1,
8543377,1499,1,379,1504,
85441,380,1509,1,883,
85452788,16,0,341,1,
8546373,1527,1,130,1532,
85471,143,2789,16,0,
8548341,1,387,2790,16,
85490,341,1,1159,2791,
855016,0,341,1,157,
85512792,16,0,341,1,
85521413,2793,16,0,341,
85531,1665,2794,16,0,
8554341,1,412,2795,16,
85550,341,1,1377,2796,
855616,0,341,1,172,
85571586,1,1939,2797,16,
85580,341,1,437,2798,
855916,0,694,1,188,
85601635,1,942,1607,1,
85611195,2799,16,0,341,
85621,1449,2800,16,0,
8563341,1,1701,2801,16,
85640,341,1,447,1628,
85651,205,2802,16,0,
8566341,1,827,2803,16,
85670,341,1,223,2804,
856816,0,341,1,476,
85691660,1,477,1666,1,
85701231,2805,16,0,341,
85711,479,1676,1,480,
85721681,1,1485,2806,16,
85730,341,1,1737,2807,
857416,0,341,1,242,
85752808,16,0,341,1,
8576478,1705,1,1001,1710,
85771,1002,1715,1,27,
85782809,19,706,1,27,
85792810,5,95,1,256,
85802811,16,0,704,1,
85811261,2812,16,0,704,
85821,509,2813,16,0,
8583704,1,1515,2814,16,
85840,704,1,2021,840,
85851,1775,2815,16,0,
8586704,1,2029,847,1,
85872030,853,1,2031,858,
85881,2032,863,1,2033,
8589868,1,277,2816,16,
85900,704,1,2035,874,
85911,2037,879,1,2039,
8592884,1,32,2817,16,
85930,704,1,2041,890,
85941,2293,2818,16,0,
8595704,1,2043,896,1,
85962045,901,1,41,2819,
859716,0,704,1,1297,
85982820,16,0,704,1,
859943,2821,16,0,704,
86001,1803,909,1,1804,
86012822,16,0,704,1,
8602299,2823,16,0,704,
86031,52,2824,16,0,
8604704,1,2318,2825,16,
86050,704,1,62,2826,
860616,0,704,1,2075,
86072827,16,0,704,1,
86081574,921,1,71,2828,
860916,0,704,1,76,
86102829,16,0,704,1,
86111834,2830,16,0,704,
86121,2337,2831,16,0,
8613704,1,79,2832,16,
86140,704,1,1335,2833,
861516,0,704,1,322,
86162834,16,0,704,1,
861785,2835,16,0,704,
86181,89,2836,16,0,
8619704,1,346,2837,16,
86200,704,1,2105,936,
86211,2106,2838,16,0,
8622704,1,97,2839,16,
86230,704,1,1860,943,
86241,2364,949,1,102,
86252840,16,0,704,1,
86262782,2841,16,0,704,
86271,112,2842,16,0,
8628704,1,1117,2843,16,
86290,704,1,1873,958,
86301,1876,2844,16,0,
8631704,1,124,2845,16,
86320,704,1,2136,965,
86331,381,2846,16,0,
8634704,1,525,2847,16,
86350,704,1,137,2848,
863616,0,704,1,1901,
86372849,16,0,704,1,
86381153,2850,16,0,704,
86391,151,2851,16,0,
8640704,1,1407,2852,16,
86410,704,1,1659,2853,
864216,0,704,1,2413,
86432854,16,0,704,1,
8644406,2855,16,0,704,
86451,1371,2856,16,0,
8646704,1,166,2857,16,
86470,704,1,1622,2858,
864816,0,704,1,1931,
8649983,1,1933,2859,16,
86500,704,1,431,2860,
865116,0,704,1,1585,
86522861,16,0,704,1,
8653182,2862,16,0,704,
86541,1189,2863,16,0,
8655704,1,1443,2864,16,
86560,704,1,1695,2865,
865716,0,704,1,2198,
86582866,16,0,704,1,
8659447,2867,16,0,704,
86601,2458,998,1,2459,
86611004,1,1958,2868,16,
86620,704,1,2462,1011,
86631,1657,1016,1,2464,
86641021,1,199,2869,16,
86650,704,1,459,2870,
866616,0,704,1,462,
86672871,16,0,704,1,
8668217,2872,16,0,704,
86691,2227,1030,1,1225,
86702873,16,0,704,1,
86711479,2874,16,0,704,
86721,1731,2875,16,0,
8673704,1,1989,1038,1,
86741990,2876,16,0,704,
86751,236,2877,16,0,
8676704,1,1756,2878,16,
86770,704,1,28,2879,
867819,734,1,28,2880,
86795,60,1,328,1425,
86801,223,1650,1,1096,
86811694,1,118,1473,1,
8682883,1515,1,525,1339,
86831,1001,1710,1,130,
86841532,1,459,1949,1,
86851114,1461,1,352,1467,
86861,447,1628,1,464,
86871944,1,1011,1224,1,
86881013,1381,1,242,1700,
86891,143,1537,1,40,
86901300,1,41,1916,1,
869142,1920,1,479,1676,
86921,44,1306,1,481,
86931951,1,373,1527,1,
869447,1307,1,157,1560,
86951,49,1319,1,50,
86961324,1,48,1313,1,
8697379,1504,1,380,1509,
86981,51,1329,1,476,
86991660,1,371,1483,1,
8700478,1705,1,1048,1462,
87011,375,1494,1,172,
87021586,1,262,1241,1,
8703283,1295,1,63,1345,
87041,67,1356,1,68,
87051361,1,69,1366,1,
870666,1351,1,461,2881,
870716,0,732,1,74,
87081376,1,377,1499,1,
87091002,1715,1,70,1371,
87101,188,1635,1,82,
87111403,1,305,1334,1,
8712477,1666,1,827,1448,
87131,93,1435,1,480,
87141681,1,205,1640,1,
8715942,1607,1,107,1455,
87161,29,2882,19,312,
87171,29,2883,5,84,
87181,1011,1224,1,1012,
87192884,16,0,310,1,
87201013,1381,1,262,1241,
87211,1267,2885,16,0,
8722310,1,515,2886,16,
87230,310,1,1521,2887,
872416,0,310,1,525,
87251339,1,2788,2888,16,
87260,310,1,283,1295,
87271,2299,2889,16,0,
8728310,1,42,2890,16,
87290,310,1,40,1300,
87301,44,1306,1,47,
87311307,1,1303,2891,16,
87320,310,1,1555,2892,
873316,0,310,1,50,
87341324,1,48,1313,1,
873549,1319,1,51,1329,
87361,63,1345,1,305,
87371334,1,66,1351,1,
873867,1356,1,68,1361,
87391,69,1366,1,70,
87401371,1,73,2893,16,
87410,310,1,74,1376,
87421,328,1425,1,1048,
87431462,1,82,2894,16,
87440,310,1,1840,2895,
874516,0,310,1,1591,
87462896,16,0,310,1,
87471341,2897,16,0,310,
87481,1096,1694,1,93,
87491435,1,352,1467,1,
8750107,2898,16,0,310,
87511,1114,1461,1,118,
87521473,1,1123,2899,16,
87530,310,1,371,1483,
87541,1628,2900,16,0,
8755310,1,375,1494,1,
87561882,2901,16,0,310,
87571,377,1499,1,379,
87581504,1,380,1509,1,
8759883,2902,16,0,310,
87601,373,1527,1,130,
87611532,1,143,1537,1,
8762387,2903,16,0,310,
87631,1159,2904,16,0,
8764310,1,157,1560,1,
87651413,2905,16,0,310,
87661,1665,2906,16,0,
8767310,1,412,2907,16,
87680,310,1,1377,2908,
876916,0,310,1,172,
87701586,1,1939,2909,16,
87710,310,1,437,2910,
877216,0,310,1,188,
87731635,1,942,1607,1,
87741195,2911,16,0,310,
87751,1449,2912,16,0,
8776310,1,1701,2913,16,
87770,310,1,447,1628,
87781,205,2914,16,0,
8779310,1,827,2915,16,
87800,310,1,223,2916,
878116,0,310,1,476,
87821660,1,477,1666,1,
87831231,2917,16,0,310,
87841,479,1676,1,480,
87851681,1,1485,2918,16,
87860,310,1,1737,2919,
878716,0,310,1,242,
87882920,16,0,310,1,
8789478,1705,1,1001,1710,
87901,1002,1715,1,30,
87912921,19,296,1,30,
87922922,5,84,1,1011,
87931224,1,1012,2923,16,
87940,294,1,1013,1381,
87951,262,1241,1,1267,
87962924,16,0,294,1,
8797515,2925,16,0,294,
87981,1521,2926,16,0,
8799294,1,525,1339,1,
88002788,2927,16,0,294,
88011,283,1295,1,2299,
88022928,16,0,294,1,
880342,2929,16,0,294,
88041,40,1300,1,44,
88051306,1,47,1307,1,
88061303,2930,16,0,294,
88071,1555,2931,16,0,
8808294,1,50,1324,1,
880948,1313,1,49,1319,
88101,51,1329,1,63,
88111345,1,305,1334,1,
881266,1351,1,67,1356,
88131,68,1361,1,69,
88141366,1,70,1371,1,
881573,2932,16,0,294,
88161,74,1376,1,328,
88171425,1,1048,1462,1,
881882,2933,16,0,294,
88191,1840,2934,16,0,
8820294,1,1591,2935,16,
88210,294,1,1341,2936,
882216,0,294,1,1096,
88231694,1,93,1435,1,
8824352,1467,1,107,2937,
882516,0,294,1,1114,
88261461,1,118,1473,1,
88271123,2938,16,0,294,
88281,371,1483,1,1628,
88292939,16,0,294,1,
8830375,1494,1,1882,2940,
883116,0,294,1,377,
88321499,1,379,1504,1,
8833380,1509,1,883,2941,
883416,0,294,1,373,
88351527,1,130,1532,1,
8836143,1537,1,387,2942,
883716,0,294,1,1159,
88382943,16,0,294,1,
8839157,1560,1,1413,2944,
884016,0,294,1,1665,
88412945,16,0,294,1,
8842412,2946,16,0,294,
88431,1377,2947,16,0,
8844294,1,172,1586,1,
88451939,2948,16,0,294,
88461,437,2949,16,0,
8847294,1,188,1635,1,
8848942,1607,1,1195,2950,
884916,0,294,1,1449,
88502951,16,0,294,1,
88511701,2952,16,0,294,
88521,447,1628,1,205,
88532953,16,0,294,1,
8854827,2954,16,0,294,
88551,223,2955,16,0,
8856294,1,476,1660,1,
8857477,1666,1,1231,2956,
885816,0,294,1,479,
88591676,1,480,1681,1,
88601485,2957,16,0,294,
88611,1737,2958,16,0,
8862294,1,242,2959,16,
88630,294,1,478,1705,
88641,1001,1710,1,1002,
88651715,1,31,2960,19,
8866281,1,31,2961,5,
886784,1,1011,1224,1,
88681012,2962,16,0,279,
88691,1013,1381,1,262,
88701241,1,1267,2963,16,
88710,279,1,515,2964,
887216,0,279,1,1521,
88732965,16,0,279,1,
8874525,1339,1,2788,2966,
887516,0,279,1,283,
88761295,1,2299,2967,16,
88770,279,1,42,2968,
887816,0,279,1,40,
88791300,1,44,1306,1,
888047,1307,1,1303,2969,
888116,0,279,1,1555,
88822970,16,0,279,1,
888350,1324,1,48,1313,
88841,49,1319,1,51,
88851329,1,63,1345,1,
8886305,1334,1,66,1351,
88871,67,1356,1,68,
88881361,1,69,1366,1,
888970,1371,1,73,2971,
889016,0,279,1,74,
88911376,1,328,1425,1,
88921048,1462,1,82,2972,
889316,0,279,1,1840,
88942973,16,0,279,1,
88951591,2974,16,0,279,
88961,1341,2975,16,0,
8897279,1,1096,1694,1,
889893,1435,1,352,1467,
88991,107,2976,16,0,
8900279,1,1114,1461,1,
8901118,1473,1,1123,2977,
890216,0,279,1,371,
89031483,1,1628,2978,16,
89040,279,1,375,1494,
89051,1882,2979,16,0,
8906279,1,377,1499,1,
8907379,1504,1,380,1509,
89081,883,2980,16,0,
8909279,1,373,1527,1,
8910130,1532,1,143,2981,
891116,0,279,1,387,
89122982,16,0,279,1,
89131159,2983,16,0,279,
89141,157,2984,16,0,
8915279,1,1413,2985,16,
89160,279,1,1665,2986,
891716,0,279,1,412,
89182987,16,0,279,1,
89191377,2988,16,0,279,
89201,172,1586,1,1939,
89212989,16,0,279,1,
8922437,2990,16,0,279,
89231,188,1635,1,942,
89241607,1,1195,2991,16,
89250,279,1,1449,2992,
892616,0,279,1,1701,
89272993,16,0,279,1,
8928447,1628,1,205,2994,
892916,0,279,1,827,
89302995,16,0,279,1,
8931223,2996,16,0,279,
89321,476,1660,1,477,
89331666,1,1231,2997,16,
89340,279,1,479,1676,
89351,480,1681,1,1485,
89362998,16,0,279,1,
89371737,2999,16,0,279,
89381,242,3000,16,0,
8939279,1,478,1705,1,
89401001,1710,1,1002,1715,
89411,32,3001,19,273,
89421,32,3002,5,84,
89431,1011,1224,1,1012,
89443003,16,0,271,1,
89451013,1381,1,262,1241,
89461,1267,3004,16,0,
8947271,1,515,3005,16,
89480,271,1,1521,3006,
894916,0,271,1,525,
89501339,1,2788,3007,16,
89510,271,1,283,1295,
89521,2299,3008,16,0,
8953271,1,42,3009,16,
89540,271,1,40,1300,
89551,44,1306,1,47,
89561307,1,1303,3010,16,
89570,271,1,1555,3011,
895816,0,271,1,50,
89591324,1,48,1313,1,
896049,1319,1,51,1329,
89611,63,1345,1,305,
89621334,1,66,1351,1,
896367,1356,1,68,1361,
89641,69,1366,1,70,
89651371,1,73,3012,16,
89660,271,1,74,1376,
89671,328,1425,1,1048,
89681462,1,82,3013,16,
89690,271,1,1840,3014,
897016,0,271,1,1591,
89713015,16,0,271,1,
89721341,3016,16,0,271,
89731,1096,1694,1,93,
89741435,1,352,1467,1,
8975107,3017,16,0,271,
89761,1114,1461,1,118,
89771473,1,1123,3018,16,
89780,271,1,371,1483,
89791,1628,3019,16,0,
8980271,1,375,1494,1,
89811882,3020,16,0,271,
89821,377,1499,1,379,
89831504,1,380,1509,1,
8984883,3021,16,0,271,
89851,373,1527,1,130,
89861532,1,143,3022,16,
89870,271,1,387,3023,
898816,0,271,1,1159,
89893024,16,0,271,1,
8990157,3025,16,0,271,
89911,1413,3026,16,0,
8992271,1,1665,3027,16,
89930,271,1,412,3028,
899416,0,271,1,1377,
89953029,16,0,271,1,
8996172,1586,1,1939,3030,
899716,0,271,1,437,
89983031,16,0,271,1,
8999188,1635,1,942,1607,
90001,1195,3032,16,0,
9001271,1,1449,3033,16,
90020,271,1,1701,3034,
900316,0,271,1,447,
90041628,1,205,3035,16,
90050,271,1,827,3036,
900616,0,271,1,223,
90073037,16,0,271,1,
9008476,1660,1,477,1666,
90091,1231,3038,16,0,
9010271,1,479,1676,1,
9011480,1681,1,1485,3039,
901216,0,271,1,1737,
90133040,16,0,271,1,
9014242,3041,16,0,271,
90151,478,1705,1,1001,
90161710,1,1002,1715,1,
901733,3042,19,370,1,
901833,3043,5,84,1,
90191011,1224,1,1012,3044,
902016,0,368,1,1013,
90211381,1,262,1241,1,
90221267,3045,16,0,368,
90231,515,3046,16,0,
9024368,1,1521,3047,16,
90250,368,1,525,1339,
90261,2788,3048,16,0,
9027368,1,283,1295,1,
90282299,3049,16,0,368,
90291,42,3050,16,0,
9030368,1,40,1300,1,
903144,1306,1,47,1307,
90321,1303,3051,16,0,
9033368,1,1555,3052,16,
90340,368,1,50,1324,
90351,48,1313,1,49,
90361319,1,51,1329,1,
903763,1345,1,305,1334,
90381,66,1351,1,67,
90391356,1,68,1361,1,
904069,1366,1,70,1371,
90411,73,3053,16,0,
9042368,1,74,1376,1,
9043328,1425,1,1048,1462,
90441,82,3054,16,0,
9045368,1,1840,3055,16,
90460,368,1,1591,3056,
904716,0,368,1,1341,
90483057,16,0,368,1,
90491096,1694,1,93,1435,
90501,352,1467,1,107,
90513058,16,0,368,1,
90521114,1461,1,118,1473,
90531,1123,3059,16,0,
9054368,1,371,1483,1,
90551628,3060,16,0,368,
90561,375,1494,1,1882,
90573061,16,0,368,1,
9058377,1499,1,379,1504,
90591,380,1509,1,883,
90603062,16,0,368,1,
9061373,1527,1,130,1532,
90621,143,1537,1,387,
90633063,16,0,368,1,
90641159,3064,16,0,368,
90651,157,1560,1,1413,
90663065,16,0,368,1,
90671665,3066,16,0,368,
90681,412,3067,16,0,
9069368,1,1377,3068,16,
90700,368,1,172,1586,
90711,1939,3069,16,0,
9072368,1,437,3070,16,
90730,368,1,188,1635,
90741,942,1607,1,1195,
90753071,16,0,368,1,
90761449,3072,16,0,368,
90771,1701,3073,16,0,
9078368,1,447,1628,1,
9079205,3074,16,0,368,
90801,827,3075,16,0,
9081368,1,223,3076,16,
90820,368,1,476,1660,
90831,477,1666,1,1231,
90843077,16,0,368,1,
9085479,1676,1,480,1681,
90861,1485,3078,16,0,
9087368,1,1737,3079,16,
90880,368,1,242,1700,
90891,478,1705,1,1001,
90901710,1,1002,1715,1,
909134,3080,19,358,1,
909234,3081,5,84,1,
90931011,1224,1,1012,3082,
909416,0,356,1,1013,
90951381,1,262,1241,1,
90961267,3083,16,0,356,
90971,515,3084,16,0,
9098356,1,1521,3085,16,
90990,356,1,525,1339,
91001,2788,3086,16,0,
9101356,1,283,1295,1,
91022299,3087,16,0,356,
91031,42,3088,16,0,
9104356,1,40,1300,1,
910544,1306,1,47,1307,
91061,1303,3089,16,0,
9107356,1,1555,3090,16,
91080,356,1,50,1324,
91091,48,1313,1,49,
91101319,1,51,1329,1,
911163,1345,1,305,1334,
91121,66,1351,1,67,
91131356,1,68,1361,1,
911469,1366,1,70,1371,
91151,73,3091,16,0,
9116356,1,74,1376,1,
9117328,1425,1,1048,1462,
91181,82,3092,16,0,
9119356,1,1840,3093,16,
91200,356,1,1591,3094,
912116,0,356,1,1341,
91223095,16,0,356,1,
91231096,1694,1,93,1435,
91241,352,1467,1,107,
91253096,16,0,356,1,
91261114,1461,1,118,1473,
91271,1123,3097,16,0,
9128356,1,371,1483,1,
91291628,3098,16,0,356,
91301,375,1494,1,1882,
91313099,16,0,356,1,
9132377,1499,1,379,1504,
91331,380,1509,1,883,
91343100,16,0,356,1,
9135373,1527,1,130,1532,
91361,143,1537,1,387,
91373101,16,0,356,1,
91381159,3102,16,0,356,
91391,157,1560,1,1413,
91403103,16,0,356,1,
91411665,3104,16,0,356,
91421,412,3105,16,0,
9143356,1,1377,3106,16,
91440,356,1,172,1586,
91451,1939,3107,16,0,
9146356,1,437,3108,16,
91470,356,1,188,1635,
91481,942,1607,1,1195,
91493109,16,0,356,1,
91501449,3110,16,0,356,
91511,1701,3111,16,0,
9152356,1,447,1628,1,
9153205,1640,1,827,3112,
915416,0,356,1,223,
91551650,1,476,1660,1,
9156477,1666,1,1231,3113,
915716,0,356,1,479,
91581676,1,480,1681,1,
91591485,3114,16,0,356,
91601,1737,3115,16,0,
9161356,1,242,1700,1,
9162478,1705,1,1001,1710,
91631,1002,1715,1,35,
91643116,19,346,1,35,
91653117,5,84,1,1011,
91661224,1,1012,3118,16,
91670,344,1,1013,1381,
91681,262,1241,1,1267,
91693119,16,0,344,1,
9170515,3120,16,0,344,
91711,1521,3121,16,0,
9172344,1,525,1339,1,
91732788,3122,16,0,344,
91741,283,1295,1,2299,
91753123,16,0,344,1,
917642,3124,16,0,344,
91771,40,1300,1,44,
91781306,1,47,1307,1,
91791303,3125,16,0,344,
91801,1555,3126,16,0,
9181344,1,50,1324,1,
918248,1313,1,49,1319,
91831,51,1329,1,63,
91841345,1,305,1334,1,
918566,1351,1,67,1356,
91861,68,1361,1,69,
91871366,1,70,1371,1,
918873,3127,16,0,344,
91891,74,1376,1,328,
91901425,1,1048,1462,1,
919182,3128,16,0,344,
91921,1840,3129,16,0,
9193344,1,1591,3130,16,
91940,344,1,1341,3131,
919516,0,344,1,1096,
91961694,1,93,1435,1,
9197352,1467,1,107,3132,
919816,0,344,1,1114,
91991461,1,118,1473,1,
92001123,3133,16,0,344,
92011,371,1483,1,1628,
92023134,16,0,344,1,
9203375,1494,1,1882,3135,
920416,0,344,1,377,
92051499,1,379,1504,1,
9206380,1509,1,883,3136,
920716,0,344,1,373,
92081527,1,130,1532,1,
9209143,1537,1,387,3137,
921016,0,344,1,1159,
92113138,16,0,344,1,
9212157,1560,1,1413,3139,
921316,0,344,1,1665,
92143140,16,0,344,1,
9215412,3141,16,0,344,
92161,1377,3142,16,0,
9217344,1,172,1586,1,
92181939,3143,16,0,344,
92191,437,3144,16,0,
9220344,1,188,1635,1,
9221942,1607,1,1195,3145,
922216,0,344,1,1449,
92233146,16,0,344,1,
92241701,3147,16,0,344,
92251,447,1628,1,205,
92261640,1,827,3148,16,
92270,344,1,223,3149,
922816,0,344,1,476,
92291660,1,477,1666,1,
92301231,3150,16,0,344,
92311,479,1676,1,480,
92321681,1,1485,3151,16,
92330,344,1,1737,3152,
923416,0,344,1,242,
92351700,1,478,1705,1,
92361001,1710,1,1002,1715,
92371,36,3153,19,242,
92381,36,3154,5,94,
92391,256,3155,16,0,
9240240,1,1261,3156,16,
92410,240,1,509,3157,
924216,0,240,1,1515,
92433158,16,0,240,1,
92442021,840,1,1775,3159,
924516,0,240,1,2029,
9246847,1,2030,853,1,
92472031,858,1,2032,863,
92481,2033,868,1,277,
92493160,16,0,240,1,
92502035,874,1,2037,879,
92511,2039,884,1,32,
92523161,16,0,240,1,
92532041,890,1,2293,3162,
925416,0,240,1,2043,
9255896,1,2045,901,1,
925641,3163,16,0,240,
92571,1297,3164,16,0,
9258240,1,43,3165,16,
92590,240,1,1803,909,
92601,1804,3166,16,0,
9261240,1,299,3167,16,
92620,240,1,52,3168,
926316,0,240,1,2318,
92643169,16,0,240,1,
92652075,3170,16,0,240,
92661,1574,921,1,71,
92673171,16,0,240,1,
926876,3172,16,0,240,
92691,1834,3173,16,0,
9270240,1,2337,3174,16,
92710,240,1,79,3175,
927216,0,240,1,1335,
92733176,16,0,240,1,
9274322,3177,16,0,240,
92751,85,3178,16,0,
9276240,1,89,3179,16,
92770,240,1,346,3180,
927816,0,240,1,2105,
9279936,1,2106,3181,16,
92800,240,1,97,3182,
928116,0,240,1,1860,
9282943,1,2364,949,1,
9283102,3183,16,0,240,
92841,2782,3184,16,0,
9285240,1,112,3185,16,
92860,240,1,1117,3186,
928716,0,240,1,1873,
9288958,1,1876,3187,16,
92890,240,1,124,3188,
929016,0,240,1,2136,
9291965,1,381,3189,16,
92920,240,1,525,3190,
929316,0,240,1,137,
92943191,16,0,240,1,
92951901,3192,16,0,240,
92961,1153,3193,16,0,
9297240,1,151,3194,16,
92980,240,1,1407,3195,
929916,0,240,1,1659,
93003196,16,0,240,1,
93012413,3197,16,0,240,
93021,406,3198,16,0,
9303240,1,1371,3199,16,
93040,240,1,166,3200,
930516,0,240,1,1622,
93063201,16,0,240,1,
93071931,983,1,1933,3202,
930816,0,240,1,431,
93093203,16,0,240,1,
93101585,3204,16,0,240,
93111,182,3205,16,0,
9312240,1,1189,3206,16,
93130,240,1,1443,3207,
931416,0,240,1,1695,
93153208,16,0,240,1,
93162198,3209,16,0,240,
93171,447,3210,16,0,
9318240,1,2458,998,1,
93192459,1004,1,1958,3211,
932016,0,240,1,2462,
93211011,1,1657,1016,1,
93222464,1021,1,199,3212,
932316,0,240,1,459,
93243213,16,0,240,1,
9325462,3214,16,0,240,
93261,217,3215,16,0,
9327240,1,2227,1030,1,
93281225,3216,16,0,240,
93291,1479,3217,16,0,
9330240,1,1731,3218,16,
93310,240,1,1989,1038,
93321,1990,3219,16,0,
9333240,1,236,3220,16,
93340,240,1,1756,3221,
933516,0,240,1,37,
93363222,19,263,1,37,
93373223,5,94,1,256,
93383224,16,0,261,1,
93391261,3225,16,0,261,
93401,509,3226,16,0,
9341261,1,1515,3227,16,
93420,261,1,2021,840,
93431,1775,3228,16,0,
9344261,1,2029,847,1,
93452030,853,1,2031,858,
93461,2032,863,1,2033,
9347868,1,277,3229,16,
93480,261,1,2035,874,
93491,2037,879,1,2039,
9350884,1,32,3230,16,
93510,261,1,2041,890,
93521,2293,3231,16,0,
9353261,1,2043,896,1,
93542045,901,1,41,3232,
935516,0,261,1,1297,
93563233,16,0,261,1,
935743,3234,16,0,261,
93581,1803,909,1,1804,
93593235,16,0,261,1,
9360299,3236,16,0,261,
93611,52,3237,16,0,
9362261,1,2318,3238,16,
93630,261,1,2075,3239,
936416,0,261,1,1574,
9365921,1,71,3240,16,
93660,261,1,76,3241,
936716,0,261,1,1834,
93683242,16,0,261,1,
93692337,3243,16,0,261,
93701,79,3244,16,0,
9371261,1,1335,3245,16,
93720,261,1,322,3246,
937316,0,261,1,85,
93743247,16,0,261,1,
937589,3248,16,0,261,
93761,346,3249,16,0,
9377261,1,2105,936,1,
93782106,3250,16,0,261,
93791,97,3251,16,0,
9380261,1,1860,943,1,
93812364,949,1,102,3252,
938216,0,261,1,2782,
93833253,16,0,261,1,
9384112,3254,16,0,261,
93851,1117,3255,16,0,
9386261,1,1873,958,1,
93871876,3256,16,0,261,
93881,124,3257,16,0,
9389261,1,2136,965,1,
9390381,3258,16,0,261,
93911,525,3259,16,0,
9392261,1,137,3260,16,
93930,261,1,1901,3261,
939416,0,261,1,1153,
93953262,16,0,261,1,
9396151,3263,16,0,261,
93971,1407,3264,16,0,
9398261,1,1659,3265,16,
93990,261,1,2413,3266,
940016,0,261,1,406,
94013267,16,0,261,1,
94021371,3268,16,0,261,
94031,166,3269,16,0,
9404261,1,1622,3270,16,
94050,261,1,1931,983,
94061,1933,3271,16,0,
9407261,1,431,3272,16,
94080,261,1,1585,3273,
940916,0,261,1,182,
94103274,16,0,261,1,
94111189,3275,16,0,261,
94121,1443,3276,16,0,
9413261,1,1695,3277,16,
94140,261,1,2198,3278,
941516,0,261,1,447,
94163279,16,0,261,1,
94172458,998,1,2459,1004,
94181,1958,3280,16,0,
9419261,1,2462,1011,1,
94201657,1016,1,2464,1021,
94211,199,3281,16,0,
9422261,1,459,3282,16,
94230,261,1,462,3283,
942416,0,261,1,217,
94253284,16,0,261,1,
94262227,1030,1,1225,3285,
942716,0,261,1,1479,
94283286,16,0,261,1,
94291731,3287,16,0,261,
94301,1989,1038,1,1990,
94313288,16,0,261,1,
9432236,3289,16,0,261,
94331,1756,3290,16,0,
9434261,1,38,3291,19,
9435260,1,38,3292,5,
943684,1,1011,1224,1,
94371012,3293,16,0,258,
94381,1013,1381,1,262,
94391241,1,1267,3294,16,
94400,258,1,515,3295,
944116,0,258,1,1521,
94423296,16,0,258,1,
9443525,1339,1,2788,3297,
944416,0,258,1,283,
94451295,1,2299,3298,16,
94460,258,1,42,3299,
944716,0,258,1,40,
94481300,1,44,1306,1,
944947,1307,1,1303,3300,
945016,0,258,1,1555,
94513301,16,0,258,1,
945250,1324,1,48,1313,
94531,49,1319,1,51,
94541329,1,63,1345,1,
9455305,1334,1,66,1351,
94561,67,1356,1,68,
94571361,1,69,1366,1,
945870,1371,1,73,3302,
945916,0,258,1,74,
94601376,1,328,1425,1,
94611048,1462,1,82,3303,
946216,0,258,1,1840,
94633304,16,0,258,1,
94641591,3305,16,0,258,
94651,1341,3306,16,0,
9466258,1,1096,1694,1,
946793,1435,1,352,1467,
94681,107,3307,16,0,
9469258,1,1114,1461,1,
9470118,1473,1,1123,3308,
947116,0,258,1,371,
94721483,1,1628,3309,16,
94730,258,1,375,1494,
94741,1882,3310,16,0,
9475258,1,377,1499,1,
9476379,1504,1,380,1509,
94771,883,1515,1,373,
94781527,1,130,1532,1,
9479143,1537,1,387,3311,
948016,0,258,1,1159,
94813312,16,0,258,1,
9482157,1560,1,1413,3313,
948316,0,258,1,1665,
94843314,16,0,258,1,
9485412,3315,16,0,258,
94861,1377,3316,16,0,
9487258,1,172,1586,1,
94881939,3317,16,0,258,
94891,437,3318,16,0,
9490258,1,188,1635,1,
9491942,1607,1,1195,3319,
949216,0,258,1,1449,
94933320,16,0,258,1,
94941701,3321,16,0,258,
94951,447,1628,1,205,
94961640,1,827,1448,1,
9497223,1650,1,476,1660,
94981,477,1666,1,1231,
94993322,16,0,258,1,
9500479,1676,1,480,1681,
95011,1485,3323,16,0,
9502258,1,1737,3324,16,
95030,258,1,242,1700,
95041,478,1705,1,1001,
95051710,1,1002,1715,1,
950639,3325,19,248,1,
950739,3326,5,84,1,
95081011,1224,1,1012,3327,
950916,0,246,1,1013,
95101381,1,262,1241,1,
95111267,3328,16,0,246,
95121,515,3329,16,0,
9513246,1,1521,3330,16,
95140,246,1,525,1339,
95151,2788,3331,16,0,
9516246,1,283,1295,1,
95172299,3332,16,0,246,
95181,42,3333,16,0,
9519246,1,40,1300,1,
952044,1306,1,47,1307,
95211,1303,3334,16,0,
9522246,1,1555,3335,16,
95230,246,1,50,1324,
95241,48,1313,1,49,
95251319,1,51,1329,1,
952663,1345,1,305,1334,
95271,66,1351,1,67,
95281356,1,68,1361,1,
952969,1366,1,70,1371,
95301,73,3336,16,0,
9531246,1,74,1376,1,
9532328,1425,1,1048,1462,
95331,82,3337,16,0,
9534246,1,1840,3338,16,
95350,246,1,1591,3339,
953616,0,246,1,1341,
95373340,16,0,246,1,
95381096,1694,1,93,1435,
95391,352,1467,1,107,
95403341,16,0,246,1,
95411114,1461,1,118,1473,
95421,1123,3342,16,0,
9543246,1,371,1483,1,
95441628,3343,16,0,246,
95451,375,1494,1,1882,
95463344,16,0,246,1,
9547377,1499,1,379,1504,
95481,380,1509,1,883,
95491515,1,373,1527,1,
9550130,1532,1,143,1537,
95511,387,3345,16,0,
9552246,1,1159,3346,16,
95530,246,1,157,1560,
95541,1413,3347,16,0,
9555246,1,1665,3348,16,
95560,246,1,412,3349,
955716,0,246,1,1377,
95583350,16,0,246,1,
9559172,1586,1,1939,3351,
956016,0,246,1,437,
95613352,16,0,246,1,
9562188,1635,1,942,1607,
95631,1195,3353,16,0,
9564246,1,1449,3354,16,
95650,246,1,1701,3355,
956616,0,246,1,447,
95671628,1,205,1640,1,
9568827,1448,1,223,1650,
95691,476,1660,1,477,
95701666,1,1231,3356,16,
95710,246,1,479,1676,
95721,480,1681,1,1485,
95733357,16,0,246,1,
95741737,3358,16,0,246,
95751,242,1700,1,478,
95761705,1,1001,1710,1,
95771002,1715,1,40,3359,
957819,236,1,40,3360,
95795,84,1,1011,1224,
95801,1012,3361,16,0,
9581234,1,1013,1381,1,
9582262,1241,1,1267,3362,
958316,0,234,1,515,
95843363,16,0,234,1,
95851521,3364,16,0,234,
95861,525,1339,1,2788,
95873365,16,0,234,1,
9588283,1295,1,2299,3366,
958916,0,234,1,42,
95903367,16,0,234,1,
959140,1300,1,44,1306,
95921,47,1307,1,1303,
95933368,16,0,234,1,
95941555,3369,16,0,234,
95951,50,1324,1,48,
95961313,1,49,1319,1,
959751,1329,1,63,1345,
95981,305,1334,1,66,
95991351,1,67,1356,1,
960068,1361,1,69,1366,
96011,70,1371,1,73,
96023370,16,0,234,1,
960374,1376,1,328,1425,
96041,1048,1462,1,82,
96053371,16,0,234,1,
96061840,3372,16,0,234,
96071,1591,3373,16,0,
9608234,1,1341,3374,16,
96090,234,1,1096,1694,
96101,93,1435,1,352,
96111467,1,107,3375,16,
96120,234,1,1114,1461,
96131,118,3376,16,0,
9614234,1,1123,3377,16,
96150,234,1,371,1483,
96161,1628,3378,16,0,
9617234,1,375,1494,1,
96181882,3379,16,0,234,
96191,377,1499,1,379,
96201504,1,380,1509,1,
9621883,3380,16,0,234,
96221,373,1527,1,130,
96233381,16,0,234,1,
9624143,3382,16,0,234,
96251,387,3383,16,0,
9626234,1,1159,3384,16,
96270,234,1,157,3385,
962816,0,234,1,1413,
96293386,16,0,234,1,
96301665,3387,16,0,234,
96311,412,3388,16,0,
9632234,1,1377,3389,16,
96330,234,1,172,3390,
963416,0,234,1,1939,
96353391,16,0,234,1,
9636437,3392,16,0,234,
96371,188,3393,16,0,
9638234,1,942,1607,1,
96391195,3394,16,0,234,
96401,1449,3395,16,0,
9641234,1,1701,3396,16,
96420,234,1,447,1628,
96431,205,3397,16,0,
9644234,1,827,3398,16,
96450,234,1,223,3399,
964616,0,234,1,476,
96471660,1,477,1666,1,
96481231,3400,16,0,234,
96491,479,1676,1,480,
96501681,1,1485,3401,16,
96510,234,1,1737,3402,
965216,0,234,1,242,
96533403,16,0,234,1,
9654478,1705,1,1001,1710,
96551,1002,1715,1,41,
96563404,19,191,1,41,
96573405,5,84,1,1011,
96581224,1,1012,3406,16,
96590,189,1,1013,1381,
96601,262,1241,1,1267,
96613407,16,0,189,1,
9662515,3408,16,0,189,
96631,1521,3409,16,0,
9664189,1,525,1339,1,
96652788,3410,16,0,189,
96661,283,1295,1,2299,
96673411,16,0,189,1,
966842,3412,16,0,189,
96691,40,1300,1,44,
96701306,1,47,1307,1,
96711303,3413,16,0,189,
96721,1555,3414,16,0,
9673189,1,50,1324,1,
967448,1313,1,49,1319,
96751,51,1329,1,63,
96761345,1,305,1334,1,
967766,1351,1,67,1356,
96781,68,1361,1,69,
96791366,1,70,1371,1,
968073,3415,16,0,189,
96811,74,1376,1,328,
96821425,1,1048,1462,1,
968382,3416,16,0,189,
96841,1840,3417,16,0,
9685189,1,1591,3418,16,
96860,189,1,1341,3419,
968716,0,189,1,1096,
96881694,1,93,1435,1,
9689352,1467,1,107,3420,
969016,0,189,1,1114,
96911461,1,118,3421,16,
96920,189,1,1123,3422,
969316,0,189,1,371,
96941483,1,1628,3423,16,
96950,189,1,375,1494,
96961,1882,3424,16,0,
9697189,1,377,1499,1,
9698379,1504,1,380,1509,
96991,883,3425,16,0,
9700189,1,373,1527,1,
9701130,3426,16,0,189,
97021,143,3427,16,0,
9703189,1,387,3428,16,
97040,189,1,1159,3429,
970516,0,189,1,157,
97063430,16,0,189,1,
97071413,3431,16,0,189,
97081,1665,3432,16,0,
9709189,1,412,3433,16,
97100,189,1,1377,3434,
971116,0,189,1,172,
97123435,16,0,189,1,
97131939,3436,16,0,189,
97141,437,3437,16,0,
9715189,1,188,3438,16,
97160,189,1,942,1607,
97171,1195,3439,16,0,
9718189,1,1449,3440,16,
97190,189,1,1701,3441,
972016,0,189,1,447,
97211628,1,205,3442,16,
97220,189,1,827,3443,
972316,0,189,1,223,
97243444,16,0,189,1,
9725476,1660,1,477,1666,
97261,1231,3445,16,0,
9727189,1,479,1676,1,
9728480,1681,1,1485,3446,
972916,0,189,1,1737,
97303447,16,0,189,1,
9731242,3448,16,0,189,
97321,478,1705,1,1001,
97331710,1,1002,1715,1,
973442,3449,19,430,1,
973542,3450,5,38,1,
97361901,3451,16,0,428,
97371,2075,3452,16,0,
9738428,1,1860,943,1,
97391803,909,1,1804,3453,
974016,0,428,1,2413,
97413454,16,0,428,1,
97422198,3455,16,0,428,
97431,1873,958,1,1657,
97441016,1,1989,1038,1,
97451990,3456,16,0,428,
97461,1775,3457,16,0,
9747428,1,32,3458,16,
97480,428,1,2105,936,
97491,2106,3459,16,0,
9750428,1,2364,949,1,
97512227,1030,1,2337,3460,
975216,0,428,1,2021,
9753840,1,2458,998,1,
97542459,1004,1,2462,1011,
97551,2136,965,1,2464,
97561021,1,2029,847,1,
97572030,853,1,2031,858,
97581,2032,863,1,2033,
9759868,1,2035,874,1,
97602037,879,1,2039,884,
97611,1931,983,1,2041,
9762890,1,2043,896,1,
97632045,901,1,1574,921,
97641,1958,3461,16,0,
9765428,1,43,3462,19,
9766518,1,43,3463,5,
976725,1,2035,874,1,
97682037,879,1,2039,884,
97691,2041,890,1,2227,
97701030,1,2043,896,1,
97711657,1016,1,1860,943,
97721,2136,965,1,2021,
9773840,1,2459,1004,1,
97741574,921,1,2105,3464,
977516,0,683,1,1931,
9776983,1,1873,958,1,
97772031,858,1,1803,909,
97781,1989,3465,16,0,
9779516,1,2464,1021,1,
97802029,847,1,2030,853,
97811,2364,949,1,2032,
9782863,1,2033,868,1,
97832045,901,1,44,3466,
978419,289,1,44,3467,
97855,38,1,1901,3468,
978616,0,287,1,2075,
97873469,16,0,287,1,
97881860,943,1,1803,909,
97891,1804,3470,16,0,
9790287,1,2413,3471,16,
97910,287,1,2198,3472,
979216,0,287,1,1873,
9793958,1,1657,1016,1,
97941989,1038,1,1990,3473,
979516,0,287,1,1775,
97963474,16,0,287,1,
979732,3475,16,0,287,
97981,2105,936,1,2106,
97993476,16,0,287,1,
98002364,949,1,2227,1030,
98011,2337,3477,16,0,
9802287,1,2021,840,1,
98032458,998,1,2459,1004,
98041,2462,1011,1,2136,
9805965,1,2464,1021,1,
98062029,847,1,2030,853,
98071,2031,858,1,2032,
9808863,1,2033,868,1,
98092035,874,1,2037,879,
98101,2039,884,1,1931,
9811983,1,2041,890,1,
98122043,896,1,2045,901,
98131,1574,921,1,1958,
98143478,16,0,287,1,
981545,3479,19,320,1,
981645,3480,5,39,1,
98171901,3481,16,0,350,
98181,2075,3482,16,0,
9819350,1,1860,943,1,
98201803,909,1,1804,3483,
982116,0,350,1,2413,
98223484,16,0,350,1,
98232198,3485,16,0,350,
98241,1873,958,1,1657,
98251016,1,1989,1038,1,
98261990,3486,16,0,350,
98271,1775,3487,16,0,
9828350,1,32,3488,16,
98290,350,1,2105,936,
98301,2106,3489,16,0,
9831350,1,2364,949,1,
98322227,1030,1,2337,3490,
983316,0,350,1,2021,
9834840,1,2458,998,1,
98352459,1004,1,2462,1011,
98361,2136,965,1,2464,
98371021,1,2029,847,1,
98382030,853,1,2031,858,
98391,2032,863,1,2033,
9840868,1,2035,874,1,
98412037,879,1,2039,884,
98421,1931,983,1,2041,
9843890,1,2043,896,1,
98442045,901,1,1832,3491,
984516,0,318,1,1574,
9846921,1,1958,3492,16,
98470,350,1,46,3493,
984819,789,1,46,3494,
98495,38,1,1901,3495,
985016,0,787,1,2075,
98513496,16,0,787,1,
98521860,943,1,1803,909,
98531,1804,3497,16,0,
9854787,1,2413,3498,16,
98550,787,1,2198,3499,
985616,0,787,1,1873,
9857958,1,1657,1016,1,
98581989,1038,1,1990,3500,
985916,0,787,1,1775,
98603501,16,0,787,1,
986132,3502,16,0,787,
98621,2105,936,1,2106,
98633503,16,0,787,1,
98642364,949,1,2227,1030,
98651,2337,3504,16,0,
9866787,1,2021,840,1,
98672458,998,1,2459,1004,
98681,2462,1011,1,2136,
9869965,1,2464,1021,1,
98702029,847,1,2030,853,
98711,2031,858,1,2032,
9872863,1,2033,868,1,
98732035,874,1,2037,879,
98741,2039,884,1,1931,
9875983,1,2041,890,1,
98762043,896,1,2045,901,
98771,1574,921,1,1958,
98783505,16,0,787,1,
987947,3506,19,660,1,
988047,3507,5,19,1,
98810,3508,16,0,760,
98821,2760,3509,16,0,
9883760,1,2779,3510,17,
98843511,15,3512,4,50,
845837,0,71,0,108, 988537,0,71,0,108,
84590,111,0,98,0, 98860,111,0,98,0,
846097,0,108,0,70, 988797,0,108,0,70,
@@ -8465,8 +9892,8 @@ public yyLSLSyntax
84650,105,0,110,0, 98920,105,0,110,0,
8466105,0,116,0,105, 9893105,0,116,0,105,
84670,111,0,110,0, 98940,111,0,110,0,
84681,-1,1,5,3203, 98951,-1,1,5,3513,
846920,3204,4,52,71, 989620,3514,4,52,71,
84700,108,0,111,0, 98970,108,0,111,0,
847198,0,97,0,108, 989898,0,97,0,108,
84720,70,0,117,0, 98990,70,0,117,0,
@@ -8476,27 +9903,47 @@ public yyLSLSyntax
84760,102,0,105,0, 99030,102,0,105,0,
8477110,0,105,0,116, 9904110,0,105,0,116,
84780,105,0,111,0, 99050,105,0,111,0,
8479110,0,95,0,50, 9906110,0,95,0,49,
84800,1,151,1,3, 99070,1,174,1,3,
84811,7,1,6,3205, 99081,6,1,5,3515,
848222,1,10,1,2640, 990922,1,9,1,2764,
8483685,1,2713,3206,17, 9910801,1,2818,3516,17,
84843207,15,3185,1,-1, 99113517,15,3518,4,52,
84851,5,3208,20,3209, 991237,0,71,0,108,
84864,38,71,0,108,
84870,111,0,98,0, 99130,111,0,98,0,
848897,0,108,0,68, 991497,0,108,0,86,
84890,101,0,102,0, 99150,97,0,114,0,
8490105,0,110,0,105, 9916105,0,97,0,98,
84910,116,0,105,0, 99170,108,0,101,0,
8492111,0,110,0,115, 991868,0,101,0,99,
84930,95,0,52,0, 99190,108,0,97,0,
84941,147,1,3,1, 9920114,0,97,0,116,
84953,1,2,3210,22, 99210,105,0,111,0,
84961,6,1,2655,3211, 9922110,0,1,-1,1,
849717,3212,15,3202,1, 99235,3519,20,3520,4,
8498-1,1,5,3213,20, 992454,71,0,108,0,
84993214,4,52,71,0, 9925111,0,98,0,97,
99260,108,0,86,0,
992797,0,114,0,105,
99280,97,0,98,0,
9929108,0,101,0,68,
99300,101,0,99,0,
9931108,0,97,0,114,
99320,97,0,116,0,
9933105,0,111,0,110,
99340,95,0,49,0,
99351,172,1,3,1,
99363,1,2,3521,22,
99371,7,1,2819,3522,
993816,0,760,1,2751,
9939807,1,2022,3523,16,
99400,658,1,2459,1004,
99411,2830,3524,16,0,
9942760,1,2647,824,1,
99432464,1021,1,2466,3525,
994417,3526,15,3512,1,
9945-1,1,5,3527,20,
99463528,4,52,71,0,
8500108,0,111,0,98, 9947108,0,111,0,98,
85010,97,0,108,0, 99480,97,0,108,0,
850270,0,117,0,110, 994970,0,117,0,110,
@@ -8506,41 +9953,73 @@ public yyLSLSyntax
8506102,0,105,0,110, 9953102,0,105,0,110,
85070,105,0,116,0, 99540,105,0,116,0,
8508105,0,111,0,110, 9955105,0,111,0,110,
85090,95,0,49,0, 99560,95,0,50,0,
85101,150,1,3,1, 99571,175,1,3,1,
85116,1,5,3215,22, 99587,1,6,3529,22,
85121,9,1,2694,3216, 99591,10,1,2837,3530,
851317,3217,15,3218,4, 996017,3531,15,3532,4,
851452,37,0,71,0, 996136,37,0,71,0,
8515108,0,111,0,98, 9962108,0,111,0,98,
85160,97,0,108,0, 99630,97,0,108,0,
851786,0,97,0,114, 996468,0,101,0,102,
85180,105,0,97,0, 99650,105,0,110,0,
851998,0,108,0,101, 9966105,0,116,0,105,
85200,68,0,101,0, 99670,111,0,110,0,
852199,0,108,0,97, 9968115,0,1,-1,1,
85220,114,0,97,0, 99695,3533,20,3534,4,
997038,71,0,108,0,
9971111,0,98,0,97,
99720,108,0,68,0,
9973101,0,102,0,105,
99740,110,0,105,0,
8523116,0,105,0,111, 9975116,0,105,0,111,
85240,110,0,1,-1, 99760,110,0,115,0,
85251,5,3219,20,3220, 997795,0,52,0,1,
85264,54,71,0,108, 9978171,1,3,1,3,
99791,2,3535,22,1,
99806,1,2838,3536,17,
99813537,15,3532,1,-1,
99821,5,3538,20,3539,
99834,38,71,0,108,
85270,111,0,98,0, 99840,111,0,98,0,
852897,0,108,0,86, 998597,0,108,0,68,
85290,97,0,114,0, 99860,101,0,102,0,
8530105,0,97,0,98, 9987105,0,110,0,105,
85310,108,0,101,0, 99880,116,0,105,0,
853268,0,101,0,99, 9989111,0,110,0,115,
85330,108,0,97,0, 99900,95,0,50,0,
8534114,0,97,0,116, 99911,169,1,3,1,
85350,105,0,111,0, 99923,1,2,3540,22,
8536110,0,95,0,49, 99931,4,1,2839,3541,
85370,1,148,1,3, 999417,3542,15,3532,1,
85381,3,1,2,3221, 9995-1,1,5,3543,20,
853922,1,7,1,2695, 99963544,4,38,71,0,
85403222,16,0,464,1, 9997108,0,111,0,98,
85412683,3223,17,3224,15, 99980,97,0,108,0,
85423218,1,-1,1,5, 999968,0,101,0,102,
85433225,20,3226,4,54, 100000,105,0,110,0,
10001105,0,116,0,105,
100020,111,0,110,0,
10003115,0,95,0,51,
100040,1,170,1,3,
100051,2,1,1,3545,
1000622,1,5,1,2840,
100073546,17,3547,15,3532,
100081,-1,1,5,3548,
1000920,3549,4,38,71,
100100,108,0,111,0,
1001198,0,97,0,108,
100120,68,0,101,0,
10013102,0,105,0,110,
100140,105,0,116,0,
10015105,0,111,0,110,
100160,115,0,95,0,
1001749,0,1,168,1,
100183,1,2,1,1,
100193550,22,1,3,1,
100202807,3551,17,3552,15,
100213518,1,-1,1,5,
100223553,20,3554,4,54,
854471,0,108,0,111, 1002371,0,108,0,111,
85450,98,0,97,0, 100240,98,0,97,0,
8546108,0,86,0,97, 10025108,0,86,0,97,
@@ -8552,2183 +10031,2826 @@ public yyLSLSyntax
855297,0,116,0,105, 1003197,0,116,0,105,
85530,111,0,110,0, 100320,111,0,110,0,
855495,0,50,0,1, 1003395,0,50,0,1,
8555149,1,3,1,5, 10034173,1,3,1,5,
85561,4,3227,22,1, 100351,4,3555,22,1,
85578,1,48,3228,19, 100368,1,2763,813,1,
8558339,1,48,3229,5, 1003748,3556,19,375,1,
855954,1,0,3230,16, 1003848,3557,5,54,1,
85600,337,1,2075,3231, 100390,3558,16,0,373,
856116,0,495,1,1860, 100401,2837,3530,1,2838,
8562821,1,1803,787,1, 100413536,1,2839,3541,1,
85631804,3232,16,0,495, 100422840,3546,1,1860,943,
85641,2413,3233,16,0, 100431,1958,3559,16,0,
8565495,1,2634,691,1, 10044573,1,2760,3560,16,
85661873,835,1,1657,894, 100450,373,1,2413,3561,
85671,2639,707,1,2640, 1004616,0,573,1,2198,
8568685,1,1989,916,1, 100473562,16,0,573,1,
85691990,3234,16,0,495, 100481873,958,1,1657,1016,
85701,2459,882,1,1775, 100491,2030,853,1,2751,
85713235,16,0,495,1, 10050807,1,1989,1038,1,
857232,3236,16,0,495, 100511990,3563,16,0,573,
85731,2105,814,1,2106, 100521,2458,998,1,2459,
85743237,16,0,495,1, 100531004,1,1775,3564,16,
85752466,3200,1,2655,3211, 100540,573,1,32,3565,
85761,2683,3223,1,2227, 1005516,0,573,1,2105,
8577908,1,2337,3238,16, 10056936,1,2106,3566,16,
85780,495,1,2558,697, 100570,573,1,2763,813,
85791,2694,3216,1,2695, 100581,2764,801,1,2227,
85803239,16,0,337,1, 100591030,1,2337,3567,16,
85812021,718,1,2458,876, 100600,573,1,2075,3568,
85821,1901,3240,16,0, 1006116,0,573,1,2779,
8583495,1,2462,889,1, 100623510,1,1803,909,1,
85842136,842,1,2464,899, 100631804,3569,16,0,573,
85851,2029,725,1,2030, 100641,1901,3570,16,0,
8586731,1,2031,736,1, 10065573,1,2462,1011,1,
85872032,741,1,2033,746, 100662136,965,1,2464,1021,
85881,2035,752,1,2364, 100671,2029,847,1,2466,
8589827,1,2715,3195,1, 100683525,1,2031,858,1,
85902039,762,1,1931,861, 100692032,863,1,2033,868,
85911,2041,768,1,2043, 100701,2035,874,1,2364,
8592774,1,2045,779,1, 10071949,1,2039,884,1,
85932198,3241,16,0,495, 100721931,983,1,2041,890,
85941,2706,3242,16,0, 100731,2021,840,1,2043,
8595337,1,2037,757,1, 10074896,1,2807,3551,1,
85962713,3206,1,2714,3183, 100752045,901,1,2647,824,
85971,1574,799,1,2716, 100761,2818,3516,1,2819,
85983189,1,2636,3243,16, 100773571,16,0,373,1,
85990,337,1,1958,3244, 100782037,879,1,1574,921,
860016,0,495,1,49, 100791,2830,3572,16,0,
86013245,19,500,1,49, 10080373,1,49,3573,19,
86023246,5,38,1,1901, 10081578,1,49,3574,5,
86033247,16,0,498,1, 1008238,1,1901,3575,16,
86042075,3248,16,0,498, 100830,576,1,2075,3576,
86051,1860,821,1,1803, 1008416,0,576,1,1860,
8606787,1,1804,3249,16, 10085943,1,1803,909,1,
86070,498,1,2413,3250, 100861804,3577,16,0,576,
860816,0,498,1,2198, 100871,2413,3578,16,0,
86093251,16,0,498,1, 10088576,1,2198,3579,16,
86101873,835,1,1657,894, 100890,576,1,1873,958,
86111,1989,916,1,1990, 100901,1657,1016,1,1989,
86123252,16,0,498,1, 100911038,1,1990,3580,16,
86131775,3253,16,0,498, 100920,576,1,1775,3581,
86141,32,3254,16,0, 1009316,0,576,1,32,
8615498,1,2105,814,1, 100943582,16,0,576,1,
86162106,3255,16,0,498, 100952105,936,1,2106,3583,
86171,2364,827,1,2227, 1009616,0,576,1,2364,
8618908,1,2337,3256,16, 10097949,1,2227,1030,1,
86190,498,1,2021,718, 100982337,3584,16,0,576,
86201,2458,876,1,2459, 100991,2021,840,1,2458,
8621882,1,2462,889,1, 10100998,1,2459,1004,1,
86222136,842,1,2464,899, 101012462,1011,1,2136,965,
86231,2029,725,1,2030, 101021,2464,1021,1,2029,
8624731,1,2031,736,1, 10103847,1,2030,853,1,
86252032,741,1,2033,746, 101042031,858,1,2032,863,
86261,2035,752,1,2037, 101051,2033,868,1,2035,
8627757,1,2039,762,1, 10106874,1,2037,879,1,
86281931,861,1,2041,768, 101072039,884,1,1931,983,
86291,2043,774,1,2045, 101081,2041,890,1,2043,
8630779,1,1574,799,1, 10109896,1,2045,901,1,
86311958,3257,16,0,498, 101101574,921,1,1958,3585,
86321,50,3258,19,614, 1011116,0,576,1,50,
86331,50,3259,5,38, 101123586,19,718,1,50,
86341,1901,3260,16,0, 101133587,5,38,1,1901,
8635612,1,2075,3261,16, 101143588,16,0,716,1,
86360,612,1,1860,821, 101152075,3589,16,0,716,
86371,1803,787,1,1804, 101161,1860,943,1,1803,
86383262,16,0,612,1, 10117909,1,1804,3590,16,
86392413,3263,16,0,612, 101180,716,1,2413,3591,
86401,2198,3264,16,0, 1011916,0,716,1,2198,
8641612,1,1873,835,1, 101203592,16,0,716,1,
86421657,894,1,1989,916, 101211873,958,1,1657,1016,
86431,1990,3265,16,0, 101221,1989,1038,1,1990,
8644612,1,1775,3266,16, 101233593,16,0,716,1,
86450,612,1,32,3267, 101241775,3594,16,0,716,
864616,0,612,1,2105, 101251,32,3595,16,0,
8647814,1,2106,3268,16, 10126716,1,2105,936,1,
86480,612,1,2364,827, 101272106,3596,16,0,716,
86491,2227,908,1,2337, 101281,2364,949,1,2227,
86503269,16,0,612,1, 101291030,1,2337,3597,16,
86512021,718,1,2458,876, 101300,716,1,2021,840,
86521,2459,882,1,2462, 101311,2458,998,1,2459,
8653889,1,2136,842,1, 101321004,1,2462,1011,1,
86542464,899,1,2029,725, 101332136,965,1,2464,1021,
86551,2030,731,1,2031, 101341,2029,847,1,2030,
8656736,1,2032,741,1, 10135853,1,2031,858,1,
86572033,746,1,2035,752, 101362032,863,1,2033,868,
86581,2037,757,1,2039, 101371,2035,874,1,2037,
8659762,1,1931,861,1, 10138879,1,2039,884,1,
86602041,768,1,2043,774, 101391931,983,1,2041,890,
86611,2045,779,1,1574, 101401,2043,896,1,2045,
8662799,1,1958,3270,16, 10141901,1,1574,921,1,
86630,612,1,51,3271, 101421958,3598,16,0,716,
866419,127,1,51,3272, 101431,51,3599,19,127,
86655,53,1,0,3273, 101441,51,3600,5,58,
866616,0,125,1,2075, 101451,0,3601,16,0,
86673274,16,0,125,1, 10146125,1,2537,3602,16,
86681860,821,1,1803,787, 101470,691,1,2837,3530,
86691,1804,3275,16,0, 101481,2838,3536,1,2839,
8670125,1,10,3276,16, 101493541,1,2840,3546,1,
86710,125,1,2413,3277, 101501860,943,1,10,3603,
867216,0,125,1,2198, 1015116,0,125,1,2413,
86733278,16,0,125,1, 101523604,16,0,125,1,
86741873,835,1,21,3279, 101532198,3605,16,0,125,
867516,0,125,1,1657, 101541,1873,958,1,21,
8676894,1,2030,731,1, 101553606,16,0,125,1,
86772642,3280,16,0,125, 101561657,1016,1,2030,853,
86781,1989,916,1,1990, 101571,1989,1038,1,1990,
86793281,16,0,125,1, 101583607,16,0,125,1,
86802459,882,1,1775,3282, 101592458,998,1,2459,1004,
868116,0,125,1,32, 101601,1775,3608,16,0,
86823283,16,0,125,1, 10161125,1,32,3609,16,
86832105,814,1,2106,3284, 101620,125,1,2105,936,
868416,0,125,1,2655, 101631,2106,3610,16,0,
86853211,1,2683,3223,1, 10164125,1,2045,901,1,
86862227,908,1,2337,3285, 101652766,3611,16,0,125,
101661,2227,1030,1,2337,
101673612,16,0,125,1,
101682075,3613,16,0,125,
101691,52,3614,16,0,
10170125,1,2560,3615,16,
101710,691,1,2779,3510,
101721,1803,909,1,1804,
101733616,16,0,125,1,
101741901,3617,16,0,125,
101751,2462,1011,1,2136,
10176965,1,2464,1021,1,
101772029,847,1,2466,3525,
101781,2031,858,1,2032,
10179863,1,2033,868,1,
101802035,874,1,2581,3618,
1018116,0,125,1,2364,
10182949,1,2039,884,1,
101831931,983,1,2041,890,
101841,2021,840,1,2043,
10185896,1,2807,3551,1,
101862510,3619,16,0,691,
101871,2514,3620,16,0,
10188691,1,2818,3516,1,
101892819,3621,16,0,125,
101901,2522,3622,16,0,
10191691,1,2037,879,1,
101921574,921,1,1958,3623,
868716,0,125,1,52, 1019316,0,125,1,52,
86883286,16,0,125,1, 101943624,19,124,1,52,
86892694,3216,1,2695,3287, 101953625,5,53,1,0,
869016,0,125,1,2021, 101963626,16,0,122,1,
8691718,1,2458,876,1, 101972837,3530,1,2838,3536,
86921901,3288,16,0,125, 101981,2839,3541,1,2840,
86931,2462,889,1,2136, 101993546,1,1860,943,1,
8694842,1,2464,899,1, 1020010,3627,16,0,122,
86952029,725,1,2466,3200, 102011,2413,3628,16,0,
86961,2031,736,1,2032, 10202122,1,2198,3629,16,
8697741,1,2033,746,1, 102030,122,1,1873,958,
86982035,752,1,2364,827, 102041,21,3630,16,0,
86991,2715,3195,1,2039, 10205122,1,1657,1016,1,
8700762,1,1931,861,1, 102062030,853,1,1989,1038,
87012041,768,1,2043,774, 102071,1990,3631,16,0,
87021,2045,779,1,2037, 10208122,1,2458,998,1,
8703757,1,2713,3206,1, 102092459,1004,1,1775,3632,
87042714,3183,1,1574,799, 1021016,0,122,1,32,
87051,2716,3189,1,1958, 102113633,16,0,122,1,
87063289,16,0,125,1, 102122105,936,1,2106,3634,
87072506,3290,16,0,125, 1021316,0,122,1,2766,
87081,52,3291,19,124, 102143635,16,0,122,1,
87091,52,3292,5,53, 102152227,1030,1,2337,3636,
87101,0,3293,16,0, 1021616,0,122,1,2075,
8711122,1,2075,3294,16, 102173637,16,0,122,1,
87120,122,1,1860,821, 1021852,3638,16,0,122,
87131,1803,787,1,1804, 102191,2779,3510,1,1803,
87143295,16,0,122,1, 10220909,1,1804,3639,16,
871510,3296,16,0,122, 102210,122,1,1901,3640,
87161,2413,3297,16,0,
8717122,1,2198,3298,16,
87180,122,1,1873,835,
87191,21,3299,16,0,
8720122,1,1657,894,1,
87212030,731,1,2642,3300,
872216,0,122,1,1989,
8723916,1,1990,3301,16,
87240,122,1,2459,882,
87251,1775,3302,16,0,
8726122,1,32,3303,16,
87270,122,1,2105,814,
87281,2106,3304,16,0,
8729122,1,2655,3211,1,
87302683,3223,1,2227,908,
87311,2337,3305,16,0,
8732122,1,52,3306,16,
87330,122,1,2694,3216,
87341,2695,3307,16,0,
8735122,1,2021,718,1,
87362458,876,1,1901,3308,
873716,0,122,1,2462, 1022216,0,122,1,2462,
8738889,1,2136,842,1, 102231011,1,2136,965,1,
87392464,899,1,2029,725, 102242464,1021,1,2029,847,
87401,2466,3200,1,2031, 102251,2466,3525,1,2031,
8741736,1,2032,741,1, 10226858,1,2032,863,1,
87422033,746,1,2035,752, 102272033,868,1,2035,874,
87431,2364,827,1,2715, 102281,2581,3641,16,0,
87443195,1,2039,762,1, 10229122,1,2364,949,1,
87451931,861,1,2041,768, 102302039,884,1,1931,983,
87461,2043,774,1,2045, 102311,2041,890,1,2021,
8747779,1,2037,757,1, 10232840,1,2043,896,1,
87482713,3206,1,2714,3183, 102332807,3551,1,2045,901,
87491,1574,799,1,2716, 102341,2818,3516,1,2819,
87503189,1,1958,3309,16, 102353642,16,0,122,1,
87510,122,1,2506,3310, 102362037,879,1,1574,921,
875216,0,122,1,53, 102371,1958,3643,16,0,
87533311,19,121,1,53, 10238122,1,53,3644,19,
87543312,5,53,1,0, 10239121,1,53,3645,5,
87553313,16,0,119,1, 1024053,1,0,3646,16,
87562075,3314,16,0,119, 102410,119,1,2837,3530,
87571,1860,821,1,1803, 102421,2838,3536,1,2839,
8758787,1,1804,3315,16, 102433541,1,2840,3546,1,
87590,119,1,10,3316, 102441860,943,1,10,3647,
876016,0,119,1,2413, 1024516,0,119,1,2413,
87613317,16,0,119,1, 102463648,16,0,119,1,
87622198,3318,16,0,119, 102472198,3649,16,0,119,
87631,1873,835,1,21, 102481,1873,958,1,21,
87643319,16,0,119,1, 102493650,16,0,119,1,
87651657,894,1,2030,731, 102501657,1016,1,2030,853,
87661,2642,3320,16,0, 102511,1989,1038,1,1990,
8767119,1,1989,916,1, 102523651,16,0,119,1,
87681990,3321,16,0,119, 102532458,998,1,2459,1004,
87691,2459,882,1,1775, 102541,1775,3652,16,0,
87703322,16,0,119,1, 10255119,1,32,3653,16,
877132,3323,16,0,119, 102560,119,1,2105,936,
87721,2105,814,1,2106, 102571,2106,3654,16,0,
87733324,16,0,119,1, 10258119,1,2766,3655,16,
87742655,3211,1,2683,3223, 102590,119,1,2227,1030,
87751,2227,908,1,2337, 102601,2337,3656,16,0,
87763325,16,0,119,1, 10261119,1,2075,3657,16,
877752,3326,16,0,119, 102620,119,1,52,3658,
87781,2694,3216,1,2695, 1026316,0,119,1,2779,
87793327,16,0,119,1, 102643510,1,1803,909,1,
87802021,718,1,2458,876, 102651804,3659,16,0,119,
87811,1901,3328,16,0, 102661,1901,3660,16,0,
8782119,1,2462,889,1, 10267119,1,2462,1011,1,
87832136,842,1,2464,899, 102682136,965,1,2464,1021,
87841,2029,725,1,2466, 102691,2029,847,1,2466,
87853200,1,2031,736,1, 102703525,1,2031,858,1,
87862032,741,1,2033,746, 102712032,863,1,2033,868,
87871,2035,752,1,2364, 102721,2035,874,1,2581,
8788827,1,2715,3195,1, 102733661,16,0,119,1,
87892039,762,1,1931,861, 102742364,949,1,2039,884,
87901,2041,768,1,2043, 102751,1931,983,1,2041,
8791774,1,2045,779,1, 10276890,1,2021,840,1,
87922037,757,1,2713,3206, 102772043,896,1,2807,3551,
87931,2714,3183,1,1574, 102781,2045,901,1,2818,
8794799,1,2716,3189,1, 102793516,1,2819,3662,16,
87951958,3329,16,0,119, 102800,119,1,2037,879,
87961,2506,3330,16,0, 102811,1574,921,1,1958,
8797119,1,54,3331,19, 102823663,16,0,119,1,
8798118,1,54,3332,5, 1028354,3664,19,118,1,
879953,1,0,3333,16, 1028454,3665,5,55,1,
88000,116,1,2075,3334, 102850,3666,16,0,116,
880116,0,116,1,1860, 102861,2837,3530,1,2838,
8802821,1,1803,787,1, 102873536,1,2839,3541,1,
88031804,3335,16,0,116, 102882840,3546,1,1860,943,
88041,10,3336,16,0, 102891,10,3667,16,0,
8805116,1,2413,3337,16, 10290116,1,2413,3668,16,
88060,116,1,2198,3338, 102910,116,1,2198,3669,
880716,0,116,1,1873, 1029216,0,116,1,1873,
8808835,1,21,3339,16, 10293958,1,21,3670,16,
88090,116,1,1657,894, 102940,116,1,1657,1016,
88101,2030,731,1,2642, 102951,2030,853,1,1989,
88113340,16,0,116,1, 102961038,1,1990,3671,16,
88121989,916,1,1990,3341, 102970,116,1,2458,998,
881316,0,116,1,2459, 102981,2459,1004,1,1775,
8814882,1,1775,3342,16, 102993672,16,0,116,1,
88150,116,1,32,3343, 1030032,3673,16,0,116,
881616,0,116,1,2105, 103011,2105,936,1,2106,
8817814,1,2106,3344,16, 103023674,16,0,116,1,
88180,116,1,2655,3211, 103032766,3675,16,0,116,
88191,2683,3223,1,2227, 103041,2227,1030,1,2337,
8820908,1,2337,3345,16, 103053676,16,0,116,1,
88210,116,1,52,3346, 103062075,3677,16,0,116,
882216,0,116,1,2694, 103071,52,3678,16,0,
88233216,1,2695,3347,16, 10308116,1,2779,3510,1,
88240,116,1,2021,718, 103091803,909,1,1804,3679,
88251,2458,876,1,1901, 1031016,0,116,1,1901,
88263348,16,0,116,1, 103113680,16,0,116,1,
88272462,889,1,2136,842, 103122462,1011,1,2136,965,
88281,2464,899,1,2029, 103131,2464,1021,1,2029,
8829725,1,2466,3200,1, 10314847,1,2466,3525,1,
88302031,736,1,2032,741, 103152031,858,1,2032,863,
88311,2033,746,1,2035, 103161,2033,868,1,2035,
8832752,1,2364,827,1, 10317874,1,2581,3681,16,
88332715,3195,1,2039,762, 103180,116,1,2364,949,
88341,1931,861,1,2041, 103191,2039,884,1,1931,
8835768,1,2043,774,1, 10320983,1,2041,890,1,
88362045,779,1,2037,757, 103212021,840,1,2043,896,
88371,2713,3206,1,2714, 103221,2807,3551,1,2045,
88383183,1,1574,799,1, 10323901,1,2568,3682,16,
88392716,3189,1,1958,3349, 103240,470,1,2818,3516,
103251,2819,3683,16,0,
10326116,1,2037,879,1,
103271574,921,1,1958,3684,
884016,0,116,1,2506, 1032816,0,116,1,2506,
88413350,16,0,116,1, 103293685,16,0,470,1,
884255,3351,19,115,1, 1033055,3686,19,115,1,
884355,3352,5,53,1, 1033155,3687,5,56,1,
88440,3353,16,0,113, 103320,3688,16,0,113,
88451,2075,3354,16,0, 103331,2837,3530,1,2838,
8846113,1,1860,821,1, 103343536,1,2839,3541,1,
88471803,787,1,1804,3355, 103352840,3546,1,1860,943,
884816,0,113,1,10, 103361,10,3689,16,0,
88493356,16,0,113,1, 10337113,1,2413,3690,16,
88502413,3357,16,0,113, 103380,113,1,2525,3691,
88511,2198,3358,16,0, 1033916,0,493,1,1657,
8852113,1,1873,835,1, 103401016,1,1873,958,1,
885321,3359,16,0,113, 1034121,3692,16,0,113,
88541,1657,894,1,2030, 103421,2529,3693,16,0,
8855731,1,2642,3360,16, 10343493,1,2030,853,1,
88560,113,1,1989,916, 103441989,1038,1,1990,3694,
88571,1990,3361,16,0, 1034516,0,113,1,2458,
8858113,1,2459,882,1, 10346998,1,2459,1004,1,
88591775,3362,16,0,113, 103471775,3695,16,0,113,
88601,32,3363,16,0, 103481,32,3696,16,0,
8861113,1,2105,814,1, 10349113,1,2105,936,1,
88622106,3364,16,0,113, 103502106,3697,16,0,113,
88631,2655,3211,1,2683, 103511,2766,3698,16,0,
88643223,1,2227,908,1, 10352113,1,2552,3699,16,
88652337,3365,16,0,113, 103530,493,1,2227,1030,
88661,52,3366,16,0, 103541,2337,3700,16,0,
8867113,1,2694,3216,1, 10355113,1,2075,3701,16,
88682695,3367,16,0,113, 103560,113,1,52,3702,
88691,2021,718,1,2458, 1035716,0,113,1,2779,
8870876,1,1901,3368,16, 103583510,1,1803,909,1,
88710,113,1,2462,889, 103591804,3703,16,0,113,
88721,2136,842,1,2464, 103601,1901,3704,16,0,
8873899,1,2029,725,1, 10361113,1,2462,1011,1,
88742466,3200,1,2031,736, 103622136,965,1,2464,1021,
88751,2032,741,1,2033, 103631,2029,847,1,2466,
8876746,1,2035,752,1, 103643525,1,2031,858,1,
88772364,827,1,2715,3195, 103652032,863,1,2033,868,
88781,2039,762,1,1931, 103661,2035,874,1,2581,
8879861,1,2041,768,1, 103673705,16,0,113,1,
88802043,774,1,2045,779, 103682364,949,1,2039,884,
88811,2037,757,1,2713, 103691,1931,983,1,2041,
88823206,1,2714,3183,1, 10370890,1,2021,840,1,
88831574,799,1,2716,3189, 103712043,896,1,2807,3551,
88841,1958,3369,16,0, 103721,2045,901,1,2198,
8885113,1,2506,3370,16, 103733706,16,0,113,1,
88860,113,1,56,3371, 103742818,3516,1,2819,3707,
888719,112,1,56,3372, 1037516,0,113,1,2037,
88885,53,1,0,3373, 10376879,1,1574,921,1,
888916,0,110,1,2075, 103771958,3708,16,0,113,
88903374,16,0,110,1, 103781,56,3709,19,112,
88911860,821,1,1803,787, 103791,56,3710,5,55,
88921,1804,3375,16,0, 103801,0,3711,16,0,
8893110,1,10,3376,16, 10381110,1,2837,3530,1,
88940,110,1,2413,3377, 103822838,3536,1,2839,3541,
103831,2840,3546,1,1860,
10384943,1,10,3712,16,
103850,110,1,2413,3713,
889516,0,110,1,2198, 1038616,0,110,1,2198,
88963378,16,0,110,1, 103873714,16,0,110,1,
88971873,835,1,21,3379, 103881873,958,1,21,3715,
889816,0,110,1,1657, 1038916,0,110,1,1657,
8899894,1,2030,731,1, 103901016,1,2030,853,1,
89002642,3380,16,0,110, 103911989,1038,1,1990,3716,
89011,1989,916,1,1990, 1039216,0,110,1,2458,
89023381,16,0,110,1, 10393998,1,2459,1004,1,
89032459,882,1,1775,3382, 103941775,3717,16,0,110,
890416,0,110,1,32, 103951,32,3718,16,0,
89053383,16,0,110,1, 10396110,1,2540,3719,16,
89062105,814,1,2106,3384, 103970,511,1,2105,936,
890716,0,110,1,2655, 103981,2106,3720,16,0,
89083211,1,2683,3223,1, 10399110,1,2544,3721,16,
89092227,908,1,2337,3385, 104000,511,1,2766,3722,
1040116,0,110,1,2227,
104021030,1,2337,3723,16,
104030,110,1,2075,3724,
891016,0,110,1,52, 1040416,0,110,1,52,
89113386,16,0,110,1, 104053725,16,0,110,1,
89122694,3216,1,2695,3387, 104062779,3510,1,1803,909,
891316,0,110,1,2021, 104071,1804,3726,16,0,
8914718,1,2458,876,1, 10408110,1,1901,3727,16,
89151901,3388,16,0,110, 104090,110,1,2462,1011,
89161,2462,889,1,2136, 104101,2136,965,1,2464,
8917842,1,2464,899,1, 104111021,1,2029,847,1,
89182029,725,1,2466,3200, 104122466,3525,1,2031,858,
89191,2031,736,1,2032, 104131,2032,863,1,2033,
8920741,1,2033,746,1, 10414868,1,2035,874,1,
89212035,752,1,2364,827, 104152581,3728,16,0,110,
89221,2715,3195,1,2039, 104161,2364,949,1,2039,
8923762,1,1931,861,1, 10417884,1,1931,983,1,
89242041,768,1,2043,774, 104182041,890,1,2021,840,
89251,2045,779,1,2037, 104191,2043,896,1,2807,
8926757,1,2713,3206,1, 104203551,1,2045,901,1,
89272714,3183,1,1574,799, 104212818,3516,1,2819,3729,
89281,2716,3189,1,1958, 1042216,0,110,1,2037,
89293389,16,0,110,1, 10423879,1,1574,921,1,
89302506,3390,16,0,110, 104241958,3730,16,0,110,
89311,57,3391,19,109, 104251,57,3731,19,109,
89321,57,3392,5,53, 104261,57,3732,5,53,
89331,0,3393,16,0, 104271,0,3733,16,0,
8934107,1,2075,3394,16, 10428107,1,2837,3530,1,
89350,107,1,1860,821, 104292838,3536,1,2839,3541,
89361,1803,787,1,1804, 104301,2840,3546,1,1860,
89373395,16,0,107,1, 10431943,1,10,3734,16,
893810,3396,16,0,107, 104320,107,1,2413,3735,
89391,2413,3397,16,0, 1043316,0,107,1,2198,
8940107,1,2198,3398,16, 104343736,16,0,107,1,
89410,107,1,1873,835, 104351873,958,1,21,3737,
89421,21,3399,16,0, 1043616,0,107,1,1657,
8943107,1,1657,894,1, 104371016,1,2030,853,1,
89442030,731,1,2642,3400, 104381989,1038,1,1990,3738,
894516,0,107,1,1989, 1043916,0,107,1,2458,
8946916,1,1990,3401,16, 10440998,1,2459,1004,1,
89470,107,1,2459,882, 104411775,3739,16,0,107,
89481,1775,3402,16,0, 104421,32,3740,16,0,
8949107,1,32,3403,16, 10443107,1,2105,936,1,
89500,107,1,2105,814, 104442106,3741,16,0,107,
89511,2106,3404,16,0, 104451,2766,3742,16,0,
8952107,1,2655,3211,1, 10446107,1,2227,1030,1,
89532683,3223,1,2227,908, 104472337,3743,16,0,107,
89541,2337,3405,16,0, 104481,2075,3744,16,0,
8955107,1,52,3406,16, 10449107,1,52,3745,16,
89560,107,1,2694,3216, 104500,107,1,2779,3510,
89571,2695,3407,16,0, 104511,1803,909,1,1804,
8958107,1,2021,718,1, 104523746,16,0,107,1,
89592458,876,1,1901,3408, 104531901,3747,16,0,107,
896016,0,107,1,2462, 104541,2462,1011,1,2136,
8961889,1,2136,842,1, 10455965,1,2464,1021,1,
89622464,899,1,2029,725, 104562029,847,1,2466,3525,
89631,2466,3200,1,2031, 104571,2031,858,1,2032,
8964736,1,2032,741,1, 10458863,1,2033,868,1,
89652033,746,1,2035,752, 104592035,874,1,2581,3748,
89661,2364,827,1,2715, 1046016,0,107,1,2364,
89673195,1,2039,762,1, 10461949,1,2039,884,1,
89681931,861,1,2041,768, 104621931,983,1,2041,890,
89691,2043,774,1,2045, 104631,2021,840,1,2043,
8970779,1,2037,757,1, 10464896,1,2807,3551,1,
89712713,3206,1,2714,3183, 104652045,901,1,2818,3516,
89721,1574,799,1,2716, 104661,2819,3749,16,0,
89733189,1,1958,3409,16, 10467107,1,2037,879,1,
89740,107,1,2506,3410, 104681574,921,1,1958,3750,
897516,0,107,1,58, 1046916,0,107,1,58,
89763411,19,429,1,58, 104703751,19,386,1,58,
89773412,5,9,1,2519, 104713752,5,30,1,2644,
89781618,1,2557,1627,1, 104721753,1,2520,1758,1,
89792521,3413,16,0,427, 104732639,1765,1,2640,1770,
89801,2559,1633,1,2597, 104741,2641,1775,1,2642,
89813414,16,0,427,1, 104751780,1,2643,1747,1,
89822561,3415,16,0,427, 104762535,1785,1,2645,1791,
89831,2459,882,1,2464, 104771,2646,1796,1,2648,
8984899,1,2470,3416,16, 104781875,1,2649,1802,1,
89850,427,1,59,3417, 104792650,1807,1,2651,1812,
898619,426,1,59,3418, 104801,2652,1817,1,2653,
89875,9,1,2519,1618, 104811822,1,2654,1827,1,
89881,2557,1627,1,2521, 104822655,1832,1,2657,3753,
89893419,16,0,424,1, 1048316,0,384,1,2550,
89902559,1633,1,2597,3420, 104841843,1,2579,1861,1,
899116,0,424,1,2561, 104852558,1849,1,2566,1855,
89923421,16,0,424,1, 104861,2459,1004,1,2464,
89932459,882,1,2464,899, 104871021,1,2574,1837,1,
89941,2470,3422,16,0, 104882470,3754,16,0,384,
8995424,1,60,3423,19, 104891,2700,3755,16,0,
8996423,1,60,3424,5, 10490384,1,2594,1868,1,
89979,1,2519,1618,1, 104912596,3756,16,0,384,
89982557,1627,1,2521,3425, 104921,59,3757,19,383,
899916,0,421,1,2559, 104931,59,3758,5,30,
90001633,1,2597,3426,16, 104941,2644,1753,1,2520,
90010,421,1,2561,3427, 104951758,1,2639,1765,1,
900216,0,421,1,2459, 104962640,1770,1,2641,1775,
9003882,1,2464,899,1, 104971,2642,1780,1,2643,
90042470,3428,16,0,421, 104981747,1,2535,1785,1,
90051,61,3429,19,420, 104992645,1791,1,2646,1796,
90061,61,3430,5,9, 105001,2648,1875,1,2649,
90071,2519,1618,1,2557, 105011802,1,2650,1807,1,
90081627,1,2521,3431,16, 105022651,1812,1,2652,1817,
90090,418,1,2559,1633, 105031,2653,1822,1,2654,
90101,2597,3432,16,0, 105041827,1,2655,1832,1,
9011418,1,2561,3433,16, 105052657,3759,16,0,381,
90120,418,1,2459,882, 105061,2550,1843,1,2579,
90131,2464,899,1,2470, 105071861,1,2558,1849,1,
90143434,16,0,418,1, 105082566,1855,1,2459,1004,
901562,3435,19,417,1, 105091,2464,1021,1,2574,
901662,3436,5,9,1, 105101837,1,2470,3760,16,
90172519,1618,1,2557,1627, 105110,381,1,2700,3761,
90181,2521,3437,16,0, 1051216,0,381,1,2594,
9019415,1,2559,1633,1, 105131868,1,2596,3762,16,
90202597,3438,16,0,415, 105140,381,1,60,3763,
90211,2561,3439,16,0, 1051519,545,1,60,3764,
9022415,1,2459,882,1, 105165,30,1,2644,1753,
90232464,899,1,2470,3440, 105171,2520,1758,1,2639,
902416,0,415,1,63, 105181765,1,2640,1770,1,
90253441,19,414,1,63, 105192641,1775,1,2642,1780,
90263442,5,9,1,2519, 105201,2643,1747,1,2535,
90271618,1,2557,1627,1, 105211785,1,2645,1791,1,
90282521,3443,16,0,412, 105222646,1796,1,2648,1875,
90291,2559,1633,1,2597, 105231,2649,1802,1,2650,
90303444,16,0,412,1, 105241807,1,2651,1812,1,
90312561,3445,16,0,412, 105252652,1817,1,2653,1822,
90321,2459,882,1,2464, 105261,2654,1827,1,2655,
9033899,1,2470,3446,16, 105271832,1,2657,3765,16,
90340,412,1,64,3447, 105280,543,1,2550,1843,
903519,653,1,64,3448, 105291,2579,1861,1,2558,
90365,9,1,2519,1618, 105301849,1,2566,1855,1,
90371,2557,1627,1,2521, 105312459,1004,1,2464,1021,
90383449,16,0,651,1, 105321,2574,1837,1,2470,
90392559,1633,1,2597,3450, 105333766,16,0,543,1,
904016,0,651,1,2561, 105342700,3767,16,0,543,
90413451,16,0,651,1, 105351,2594,1868,1,2596,
90422459,882,1,2464,899, 105363768,16,0,543,1,
90431,2470,3452,16,0, 1053761,3769,19,423,1,
9044651,1,65,3453,19, 1053861,3770,5,30,1,
9045410,1,65,3454,5, 105392644,1753,1,2520,1758,
90469,1,2519,1618,1, 105401,2639,1765,1,2640,
90472557,1627,1,2521,3455, 105411770,1,2641,1775,1,
904816,0,408,1,2559, 105422642,1780,1,2643,1747,
90491633,1,2597,3456,16, 105431,2535,1785,1,2645,
90500,408,1,2561,3457, 105441791,1,2646,1796,1,
905116,0,408,1,2459, 105452648,1875,1,2649,1802,
9052882,1,2464,899,1, 105461,2650,1807,1,2651,
90532470,3458,16,0,408, 105471812,1,2652,1817,1,
90541,66,3459,19,493, 105482653,1822,1,2654,1827,
90551,66,3460,5,9, 105491,2655,1832,1,2657,
90561,2519,1618,1,2557, 105503771,16,0,421,1,
90571627,1,2521,3461,16, 105512550,1843,1,2579,1861,
90580,491,1,2559,1633, 105521,2558,1849,1,2566,
90591,2597,3462,16,0, 105531855,1,2459,1004,1,
9060491,1,2561,3463,16, 105542464,1021,1,2574,1837,
90610,491,1,2459,882, 105551,2470,3772,16,0,
90621,2464,899,1,2470, 10556421,1,2700,3773,16,
90633464,16,0,491,1, 105570,421,1,2594,1868,
906467,3465,19,406,1, 105581,2596,3774,16,0,
906567,3466,5,9,1, 10559421,1,62,3775,19,
90662519,1618,1,2557,1627, 10560541,1,62,3776,5,
90671,2521,3467,16,0, 1056130,1,2644,1753,1,
9068404,1,2559,1633,1, 105622520,1758,1,2639,1765,
90692597,3468,16,0,404, 105631,2640,1770,1,2641,
90701,2561,3469,16,0, 105641775,1,2642,1780,1,
9071404,1,2459,882,1, 105652643,1747,1,2535,1785,
90722464,899,1,2470,3470, 105661,2645,1791,1,2646,
907316,0,404,1,68, 105671796,1,2648,1875,1,
90743471,19,403,1,68, 105682649,1802,1,2650,1807,
90753472,5,9,1,2519, 105691,2651,1812,1,2652,
90761618,1,2557,1627,1, 105701817,1,2653,1822,1,
90772521,3473,16,0,401, 105712654,1827,1,2655,1832,
90781,2559,1633,1,2597, 105721,2657,3777,16,0,
90793474,16,0,401,1, 10573539,1,2550,1843,1,
90802561,3475,16,0,401, 105742579,1861,1,2558,1849,
90811,2459,882,1,2464, 105751,2566,1855,1,2459,
9082899,1,2470,3476,16, 105761004,1,2464,1021,1,
90830,401,1,69,3477, 105772574,1837,1,2470,3778,
908419,486,1,69,3478, 1057816,0,539,1,2700,
90855,9,1,2519,1618, 105793779,16,0,539,1,
90861,2557,1627,1,2521, 105802594,1868,1,2596,3780,
90873479,16,0,484,1, 1058116,0,539,1,63,
90882559,1633,1,2597,3480, 105823781,19,653,1,63,
908916,0,484,1,2561, 105833782,5,30,1,2644,
90903481,16,0,484,1, 105841753,1,2520,1758,1,
90912459,882,1,2464,899, 105852639,1765,1,2640,1770,
90921,2470,3482,16,0, 105861,2641,1775,1,2642,
9093484,1,70,3483,19, 105871780,1,2643,1747,1,
9094399,1,70,3484,5, 105882535,1785,1,2645,1791,
90959,1,2519,1618,1, 105891,2646,1796,1,2648,
90962557,1627,1,2521,3485, 105901875,1,2649,1802,1,
909716,0,397,1,2559, 105912650,1807,1,2651,1812,
90981633,1,2597,3486,16, 105921,2652,1817,1,2653,
90990,397,1,2561,3487, 105931822,1,2654,1827,1,
910016,0,397,1,2459, 105942655,1832,1,2657,3783,
9101882,1,2464,899,1, 1059516,0,651,1,2550,
91022470,3488,16,0,397, 105961843,1,2579,1861,1,
91031,71,3489,19,483, 105972558,1849,1,2566,1855,
91041,71,3490,5,9, 105981,2459,1004,1,2464,
91051,2519,1618,1,2557, 105991021,1,2574,1837,1,
91061627,1,2521,3491,16, 106002470,3784,16,0,651,
91070,481,1,2559,1633, 106011,2700,3785,16,0,
91081,2597,3492,16,0, 10602651,1,2594,1868,1,
9109481,1,2561,3493,16, 106032596,3786,16,0,651,
91100,481,1,2459,882, 106041,64,3787,19,416,
91111,2464,899,1,2470, 106051,64,3788,5,30,
91123494,16,0,481,1, 106061,2644,1753,1,2520,
911372,3495,19,480,1, 106071758,1,2639,1765,1,
911472,3496,5,9,1, 106082640,1770,1,2641,1775,
91152519,1618,1,2557,1627, 106091,2642,1780,1,2643,
91161,2521,3497,16,0, 106101747,1,2535,1785,1,
9117478,1,2559,1633,1, 106112645,1791,1,2646,1796,
91182597,3498,16,0,478, 106121,2648,1875,1,2649,
91191,2561,3499,16,0, 106131802,1,2650,1807,1,
9120478,1,2459,882,1, 106142651,1812,1,2652,1817,
91212464,899,1,2470,3500, 106151,2653,1822,1,2654,
912216,0,478,1,73, 106161827,1,2655,1832,1,
91233501,19,477,1,73, 106172657,3789,16,0,414,
91243502,5,9,1,2519, 106181,2550,1843,1,2579,
91251618,1,2557,1627,1, 106191861,1,2558,1849,1,
91262521,3503,16,0,475, 106202566,1855,1,2459,1004,
91271,2559,1633,1,2597, 106211,2464,1021,1,2574,
91283504,16,0,475,1, 106221837,1,2470,3790,16,
91292561,3505,16,0,475, 106230,414,1,2700,3791,
91301,2459,882,1,2464, 1062416,0,414,1,2594,
9131899,1,2470,3506,16, 106251868,1,2596,3792,16,
91320,475,1,74,3507, 106260,414,1,65,3793,
913319,474,1,74,3508, 1062719,380,1,65,3794,
91345,9,1,2519,1618, 106285,30,1,2644,1753,
91351,2557,1627,1,2521, 106291,2520,1758,1,2639,
91363509,16,0,472,1, 106301765,1,2640,1770,1,
91372559,1633,1,2597,3510, 106312641,1775,1,2642,1780,
913816,0,472,1,2561, 106321,2643,1747,1,2535,
91393511,16,0,472,1, 106331785,1,2645,1791,1,
91402459,882,1,2464,899, 106342646,1796,1,2648,1875,
91411,2470,3512,16,0, 106351,2649,1802,1,2650,
9142472,1,75,3513,19, 106361807,1,2651,1812,1,
9143390,1,75,3514,5, 106372652,1817,1,2653,1822,
91449,1,2519,1618,1, 106381,2654,1827,1,2655,
91452557,1627,1,2521,3515, 106391832,1,2657,3795,16,
914616,0,388,1,2559, 106400,378,1,2550,1843,
91471633,1,2597,3516,16, 106411,2579,1861,1,2558,
91480,388,1,2561,3517, 106421849,1,2566,1855,1,
914916,0,388,1,2459, 106432459,1004,1,2464,1021,
9150882,1,2464,899,1, 106441,2574,1837,1,2470,
91512470,3518,16,0,388, 106453796,16,0,378,1,
91521,76,3519,19,387, 106462700,3797,16,0,378,
91531,76,3520,5,9, 106471,2594,1868,1,2596,
91541,2519,1618,1,2557, 106483798,16,0,378,1,
91551627,1,2521,3521,16, 1064966,3799,19,465,1,
91560,385,1,2559,1633, 1065066,3800,5,30,1,
91571,2597,3522,16,0, 106512644,1753,1,2520,1758,
9158385,1,2561,3523,16, 106521,2639,1765,1,2640,
91590,385,1,2459,882, 106531770,1,2641,1775,1,
91601,2464,899,1,2470, 106542642,1780,1,2643,1747,
91613524,16,0,385,1, 106551,2535,1785,1,2645,
916277,3525,19,471,1, 106561791,1,2646,1796,1,
916377,3526,5,9,1, 106572648,1875,1,2649,1802,
91642519,1618,1,2557,1627, 106581,2650,1807,1,2651,
91651,2521,3527,16,0, 106591812,1,2652,1817,1,
9166469,1,2559,1633,1, 106602653,1822,1,2654,1827,
91672597,3528,16,0,469, 106611,2655,1832,1,2657,
91681,2561,3529,16,0, 106623801,16,0,463,1,
9169469,1,2459,882,1, 106632550,1843,1,2579,1861,
91702464,899,1,2470,3530, 106641,2558,1849,1,2566,
917116,0,469,1,78, 106651855,1,2459,1004,1,
91723531,19,566,1,78, 106662464,1021,1,2574,1837,
91733532,5,9,1,2519, 106671,2470,3802,16,0,
91741618,1,2557,1627,1, 10668463,1,2700,3803,16,
91752521,3533,16,0,564, 106690,463,1,2594,1868,
91761,2559,1633,1,2597, 106701,2596,3804,16,0,
91773534,16,0,564,1, 10671463,1,67,3805,19,
91782561,3535,16,0,564, 10672462,1,67,3806,5,
91791,2459,882,1,2464, 1067330,1,2644,1753,1,
9180899,1,2470,3536,16, 106742520,1758,1,2639,1765,
91810,564,1,79,3537, 106751,2640,1770,1,2641,
918219,380,1,79,3538, 106761775,1,2642,1780,1,
91835,9,1,2519,1618, 106772643,1747,1,2535,1785,
91841,2557,1627,1,2521, 106781,2645,1791,1,2646,
91853539,16,0,378,1, 106791796,1,2648,1875,1,
91862559,1633,1,2597,3540, 106802649,1802,1,2650,1807,
918716,0,378,1,2561, 106811,2651,1812,1,2652,
91883541,16,0,378,1, 106821817,1,2653,1822,1,
91892459,882,1,2464,899, 106832654,1827,1,2655,1832,
91901,2470,3542,16,0, 106841,2657,3807,16,0,
9191378,1,80,3543,19, 10685460,1,2550,1843,1,
9192377,1,80,3544,5, 106862579,1861,1,2558,1849,
91939,1,2519,1618,1, 106871,2566,1855,1,2459,
91942557,1627,1,2521,3545, 106881004,1,2464,1021,1,
919516,0,375,1,2559, 106892574,1837,1,2470,3808,
91961633,1,2597,3546,16, 1069016,0,460,1,2700,
91970,375,1,2561,3547, 106913809,16,0,460,1,
919816,0,375,1,2459, 106922594,1868,1,2596,3810,
9199882,1,2464,899,1, 1069316,0,460,1,68,
92002470,3548,16,0,375, 106943811,19,459,1,68,
92011,81,3549,19,374, 106953812,5,30,1,2644,
92021,81,3550,5,9, 106961753,1,2520,1758,1,
92031,2519,1618,1,2557, 106972639,1765,1,2640,1770,
92041627,1,2521,3551,16, 106981,2641,1775,1,2642,
92050,372,1,2559,1633, 106991780,1,2643,1747,1,
92061,2597,3552,16,0, 107002535,1785,1,2645,1791,
9207372,1,2561,3553,16, 107011,2646,1796,1,2648,
92080,372,1,2459,882, 107021875,1,2649,1802,1,
92091,2464,899,1,2470, 107032650,1807,1,2651,1812,
92103554,16,0,372,1, 107041,2652,1817,1,2653,
921182,3555,19,371,1, 107051822,1,2654,1827,1,
921282,3556,5,9,1, 107062655,1832,1,2657,3813,
92132519,1618,1,2557,1627, 1070716,0,457,1,2550,
92141,2521,3557,16,0, 107081843,1,2579,1861,1,
9215369,1,2559,1633,1, 107092558,1849,1,2566,1855,
92162597,3558,16,0,369, 107101,2459,1004,1,2464,
92171,2561,3559,16,0, 107111021,1,2574,1837,1,
9218369,1,2459,882,1, 107122470,3814,16,0,457,
92192464,899,1,2470,3560, 107131,2700,3815,16,0,
922016,0,369,1,83, 10714457,1,2594,1868,1,
92213561,19,368,1,83, 107152596,3816,16,0,457,
92223562,5,9,1,2519, 107161,69,3817,19,395,
92231618,1,2557,1627,1, 107171,69,3818,5,30,
92242521,3563,16,0,366, 107181,2644,1753,1,2520,
92251,2559,1633,1,2597, 107191758,1,2639,1765,1,
92263564,16,0,366,1, 107202640,1770,1,2641,1775,
92272561,3565,16,0,366, 107211,2642,1780,1,2643,
92281,2459,882,1,2464, 107221747,1,2535,1785,1,
9229899,1,2470,3566,16, 107232645,1791,1,2646,1796,
92300,366,1,84,3567, 107241,2648,1875,1,2649,
923119,365,1,84,3568, 107251802,1,2650,1807,1,
92325,9,1,2519,1618, 107262651,1812,1,2652,1817,
92331,2557,1627,1,2521, 107271,2653,1822,1,2654,
92343569,16,0,363,1, 107281827,1,2655,1832,1,
92352559,1633,1,2597,3570, 107292657,3819,16,0,393,
923616,0,363,1,2561, 107301,2550,1843,1,2579,
92373571,16,0,363,1, 107311861,1,2558,1849,1,
92382459,882,1,2464,899, 107322566,1855,1,2459,1004,
92391,2470,3572,16,0, 107331,2464,1021,1,2574,
9240363,1,85,3573,19, 107341837,1,2470,3820,16,
9241362,1,85,3574,5, 107350,393,1,2700,3821,
92429,1,2519,1618,1, 1073616,0,393,1,2594,
92432557,1627,1,2521,3575, 107371868,1,2596,3822,16,
924416,0,360,1,2559, 107380,393,1,70,3823,
92451633,1,2597,3576,16, 1073919,392,1,70,3824,
92460,360,1,2561,3577, 107405,30,1,2644,1753,
924716,0,360,1,2459, 107411,2520,1758,1,2639,
9248882,1,2464,899,1, 107421765,1,2640,1770,1,
92492470,3578,16,0,360, 107432641,1775,1,2642,1780,
92501,86,3579,19,359, 107441,2643,1747,1,2535,
92511,86,3580,5,9, 107451785,1,2645,1791,1,
92521,2519,1618,1,2557, 107462646,1796,1,2648,1875,
92531627,1,2521,3581,16, 107471,2649,1802,1,2650,
92540,357,1,2559,1633, 107481807,1,2651,1812,1,
92551,2597,3582,16,0, 107492652,1817,1,2653,1822,
9256357,1,2561,3583,16, 107501,2654,1827,1,2655,
92570,357,1,2459,882, 107511832,1,2657,3825,16,
92581,2464,899,1,2470, 107520,390,1,2550,1843,
92593584,16,0,357,1, 107531,2579,1861,1,2558,
926087,3585,19,356,1, 107541849,1,2566,1855,1,
926187,3586,5,9,1, 107552459,1004,1,2464,1021,
92622519,1618,1,2557,1627, 107561,2574,1837,1,2470,
92631,2521,3587,16,0, 107573826,16,0,390,1,
9264354,1,2559,1633,1, 107582700,3827,16,0,390,
92652597,3588,16,0,354, 107591,2594,1868,1,2596,
92661,2561,3589,16,0, 107603828,16,0,390,1,
9267354,1,2459,882,1, 1076171,3829,19,389,1,
92682464,899,1,2470,3590, 1076271,3830,5,30,1,
926916,0,354,1,88, 107632644,1753,1,2520,1758,
92703591,19,353,1,88, 107641,2639,1765,1,2640,
92713592,5,9,1,2519, 107651770,1,2641,1775,1,
92721618,1,2557,1627,1, 107662642,1780,1,2643,1747,
92732521,3593,16,0,351, 107671,2535,1785,1,2645,
92741,2559,1633,1,2597, 107681791,1,2646,1796,1,
92753594,16,0,351,1, 107692648,1875,1,2649,1802,
92762561,3595,16,0,351, 107701,2650,1807,1,2651,
92771,2459,882,1,2464, 107711812,1,2652,1817,1,
9278899,1,2470,3596,16, 107722653,1822,1,2654,1827,
92790,351,1,89,3597, 107731,2655,1832,1,2657,
928019,347,1,89,3598, 107743831,16,0,387,1,
92815,9,1,2519,1618, 107752550,1843,1,2579,1861,
92821,2557,1627,1,2521, 107761,2558,1849,1,2566,
92833599,16,0,345,1, 107771855,1,2459,1004,1,
92842559,1633,1,2597,3600, 107782464,1021,1,2574,1837,
928516,0,345,1,2561, 107791,2470,3832,16,0,
92863601,16,0,345,1, 10780387,1,2700,3833,16,
92872459,882,1,2464,899, 107810,387,1,2594,1868,
92881,2470,3602,16,0, 107821,2596,3834,16,0,
9289345,1,90,3603,19, 10783387,1,72,3835,19,
9290350,1,90,3604,5, 10784456,1,72,3836,5,
92919,1,2519,1618,1, 1078530,1,2644,1753,1,
92922557,1627,1,2521,3605, 107862520,1758,1,2639,1765,
929316,0,348,1,2559, 107871,2640,1770,1,2641,
92941633,1,2597,3606,16, 107881775,1,2642,1780,1,
92950,348,1,2561,3607, 107892643,1747,1,2535,1785,
929616,0,348,1,2459, 107901,2645,1791,1,2646,
9297882,1,2464,899,1, 107911796,1,2648,1875,1,
92982470,3608,16,0,348, 107922649,1802,1,2650,1807,
92991,91,3609,19,344, 107931,2651,1812,1,2652,
93001,91,3610,5,9, 107941817,1,2653,1822,1,
93011,2519,1618,1,2557, 107952654,1827,1,2655,1832,
93021627,1,2521,3611,16, 107961,2657,3837,16,0,
93030,342,1,2559,1633, 10797454,1,2550,1843,1,
93041,2597,3612,16,0, 107982579,1861,1,2558,1849,
9305342,1,2561,3613,16, 107991,2566,1855,1,2459,
93060,342,1,2459,882, 108001004,1,2464,1021,1,
93071,2464,899,1,2470, 108012574,1837,1,2470,3838,
93083614,16,0,342,1, 1080216,0,454,1,2700,
930992,3615,19,133,1, 108033839,16,0,454,1,
931092,3616,5,125,1, 108042594,1868,1,2596,3840,
93110,3617,16,0,563, 1080516,0,454,1,73,
93121,1,1951,1,2, 108063841,19,453,1,73,
93131957,1,3,1962,1, 108073842,5,30,1,2644,
93144,1967,1,5,1972, 108081753,1,2520,1758,1,
93151,6,1977,1,7, 108092639,1765,1,2640,1770,
93161982,1,8,3618,16, 108101,2641,1775,1,2642,
93170,131,1,1515,3619, 108111780,1,2643,1747,1,
931816,0,165,1,2021, 108122535,1785,1,2645,1791,
9319718,1,2022,3620,16, 108131,2646,1796,1,2648,
93200,497,1,256,3621, 108141875,1,2649,1802,1,
932116,0,173,1,2025, 108152650,1807,1,2651,1812,
93223622,16,0,501,1, 108161,2652,1817,1,2653,
932318,3623,16,0,138, 108171822,1,2654,1827,1,
93241,2027,3624,16,0, 108182655,1832,1,2657,3843,
9325505,1,2695,3625,16, 1081916,0,451,1,2550,
93260,563,1,2029,725, 108201843,1,2579,1861,1,
93271,2030,731,1,2031, 108212558,1849,1,2566,1855,
9328736,1,2032,741,1, 108221,2459,1004,1,2464,
93292033,746,1,277,3626, 108231021,1,2574,1837,1,
933016,0,173,1,2035, 108242470,3844,16,0,451,
9331752,1,2037,757,1, 108251,2700,3845,16,0,
93322039,762,1,32,3627, 10826451,1,2594,1868,1,
933316,0,165,1,2041, 108272596,3846,16,0,451,
9334768,1,2293,3628,16, 108281,74,3847,19,450,
93350,173,1,2043,774, 108291,74,3848,5,30,
93361,2045,779,1,2713, 108301,2644,1753,1,2520,
93373206,1,2715,3195,1, 108311758,1,2639,1765,1,
933841,3629,16,0,173, 108322640,1770,1,2641,1775,
93391,1297,3630,16,0, 108331,2642,1780,1,2643,
9340165,1,43,3631,16, 108341747,1,2535,1785,1,
93410,173,1,46,3632, 108352645,1791,1,2646,1796,
934216,0,178,1,1804, 108361,2648,1875,1,2649,
93433633,16,0,165,1, 108371802,1,2650,1807,1,
9344299,3634,16,0,173, 108382651,1812,1,2652,1817,
93451,52,3635,16,0, 108391,2653,1822,1,2654,
9346165,1,509,3636,16, 108401827,1,2655,1832,1,
93470,173,1,2318,3637, 108412657,3849,16,0,448,
934816,0,165,1,62, 108421,2550,1843,1,2579,
93493638,16,0,195,1, 108431861,1,2558,1849,1,
935065,3639,16,0,197, 108442566,1855,1,2459,1004,
93511,2075,3640,16,0, 108451,2464,1021,1,2574,
9352165,1,1574,799,1, 108461837,1,2470,3850,16,
935371,3641,16,0,173, 108470,448,1,2700,3851,
93541,1775,3642,16,0, 1084816,0,448,1,2594,
9355165,1,76,3643,16, 108491868,1,2596,3852,16,
93560,173,1,1834,3644, 108500,448,1,75,3853,
935716,0,165,1,2337, 1085119,439,1,75,3854,
93583645,16,0,165,1, 108525,30,1,2644,1753,
935979,3646,16,0,173, 108531,2520,1758,1,2639,
93601,1335,3647,16,0, 108541765,1,2640,1770,1,
9361165,1,322,3648,16, 108552641,1775,1,2642,1780,
93620,173,1,85,3649, 108561,2643,1747,1,2535,
936316,0,173,1,1261, 108571785,1,2645,1791,1,
93643650,16,0,165,1, 108582646,1796,1,2648,1875,
936589,3651,16,0,173, 108591,2649,1802,1,2650,
93661,346,3652,16,0, 108601807,1,2651,1812,1,
9367173,1,97,3653,16, 108612652,1817,1,2653,1822,
93680,173,1,2106,3654, 108621,2654,1827,1,2655,
936916,0,165,1,102, 108631832,1,2657,3855,16,
93703655,16,0,173,1, 108640,437,1,2550,1843,
93711860,821,1,1803,787, 108651,2579,1861,1,2558,
93721,2364,827,1,1113, 108661849,1,2566,1855,1,
93733656,16,0,158,1, 108672459,1004,1,2464,1021,
9374112,3657,16,0,173, 108681,2574,1837,1,2470,
93751,1117,3658,16,0, 108693856,16,0,437,1,
9376165,1,1873,835,1, 108702700,3857,16,0,437,
93771876,3659,16,0,165, 108711,2594,1868,1,2596,
93781,372,3660,16,0, 108723858,16,0,437,1,
9379535,1,374,3661,16, 1087376,3859,19,560,1,
93800,537,1,124,3662, 1087476,3860,5,30,1,
938116,0,173,1,376, 108752644,1753,1,2520,1758,
93823663,16,0,539,1, 108761,2639,1765,1,2640,
9383378,3664,16,0,541, 108771770,1,2641,1775,1,
93841,2136,842,1,381, 108782642,1780,1,2643,1747,
93853665,16,0,173,1, 108791,2535,1785,1,2645,
9386525,3666,16,0,173, 108801791,1,2646,1796,1,
93871,137,3667,16,0, 108812648,1875,1,2649,1802,
9388173,1,1901,3668,16, 108821,2650,1807,1,2651,
93890,165,1,2655,3211, 108831812,1,2652,1817,1,
93901,2658,3669,16,0, 108842653,1822,1,2654,1827,
9391173,1,1153,3670,16, 108851,2655,1832,1,2657,
93920,165,1,151,3671, 108863861,16,0,558,1,
939316,0,173,1,1407, 108872550,1843,1,2579,1861,
93943672,16,0,165,1, 108881,2558,1849,1,2566,
93951659,3673,16,0,165, 108891855,1,2459,1004,1,
93961,2413,3674,16,0, 108902464,1021,1,2574,1837,
9397165,1,406,3675,16, 108911,2470,3862,16,0,
93980,173,1,1371,3676, 10892558,1,2700,3863,16,
939916,0,165,1,2105, 108930,558,1,2594,1868,
9400814,1,1657,894,1, 108941,2596,3864,16,0,
9401166,3677,16,0,173, 10895558,1,77,3865,19,
94021,1622,3678,16,0, 10896435,1,77,3866,5,
9403173,1,2683,3223,1, 1089730,1,2644,1753,1,
94041931,861,1,1933,3679, 108982520,1758,1,2639,1765,
940516,0,165,1,431, 108991,2640,1770,1,2641,
94063680,16,0,173,1, 109001775,1,2642,1780,1,
94071585,3681,16,0,173, 109012643,1747,1,2535,1785,
94081,182,3682,16,0, 109021,2645,1791,1,2646,
9409173,1,2694,3216,1, 109031796,1,2648,1875,1,
94101189,3683,16,0,165, 109042649,1802,1,2650,1807,
94111,1443,3684,16,0, 109051,2651,1812,1,2652,
9412165,1,1695,3685,16, 109061817,1,2653,1822,1,
94130,165,1,2198,3686, 109072654,1827,1,2655,1832,
941416,0,165,1,447, 109081,2657,3867,16,0,
94153687,16,0,173,1, 10909433,1,2550,1843,1,
94162458,876,1,2459,882, 109102579,1861,1,2558,1849,
94171,1958,3688,16,0, 109111,2566,1855,1,2459,
9418165,1,2462,889,1, 109121004,1,2464,1021,1,
94192714,3183,1,2464,899, 109132574,1837,1,2470,3868,
94201,2716,3189,1,2466, 1091416,0,433,1,2700,
94213200,1,459,3689,16, 109153869,16,0,433,1,
94220,173,1,2468,3690, 109162594,1868,1,2596,3870,
942316,0,340,1,462, 1091716,0,433,1,78,
94243691,16,0,173,1, 109183871,19,554,1,78,
9425199,3692,16,0,173, 109193872,5,30,1,2644,
94261,217,3693,16,0, 109201753,1,2520,1758,1,
9427173,1,2227,908,1, 109212639,1765,1,2640,1770,
94281225,3694,16,0,165, 109221,2641,1775,1,2642,
94291,1479,3695,16,0, 109231780,1,2643,1747,1,
9430165,1,1731,3696,16, 109242535,1785,1,2645,1791,
94310,173,1,1989,916, 109251,2646,1796,1,2648,
94321,1990,3697,16,0, 109261875,1,2649,1802,1,
9433165,1,236,3698,16, 109272650,1807,1,2651,1812,
94340,173,1,1756,3699, 109281,2652,1817,1,2653,
943516,0,165,1,93, 109291822,1,2654,1827,1,
94363700,19,626,1,93, 109302655,1832,1,2657,3873,
94373701,5,95,1,256, 1093116,0,552,1,2550,
94383702,16,0,624,1, 109321843,1,2579,1861,1,
94391261,3703,16,0,624, 109332558,1849,1,2566,1855,
94401,509,3704,16,0, 109341,2459,1004,1,2464,
9441624,1,1515,3705,16, 109351021,1,2574,1837,1,
94420,624,1,2021,718, 109362470,3874,16,0,552,
94431,1775,3706,16,0, 109371,2700,3875,16,0,
9444624,1,2029,725,1, 10938552,1,2594,1868,1,
94452030,731,1,2031,736, 109392596,3876,16,0,552,
94461,2032,741,1,2033, 109401,79,3877,19,551,
9447746,1,277,3707,16, 109411,79,3878,5,30,
94480,624,1,2035,752, 109421,2644,1753,1,2520,
94491,2037,757,1,2039, 109431758,1,2639,1765,1,
9450762,1,32,3708,16, 109442640,1770,1,2641,1775,
94510,624,1,2041,768, 109451,2642,1780,1,2643,
94521,2293,3709,16,0, 109461747,1,2535,1785,1,
9453624,1,2043,774,1, 109472645,1791,1,2646,1796,
94542045,779,1,41,3710, 109481,2648,1875,1,2649,
945516,0,624,1,1297, 109491802,1,2650,1807,1,
94563711,16,0,624,1, 109502651,1812,1,2652,1817,
945743,3712,16,0,624, 109511,2653,1822,1,2654,
94581,1803,787,1,1804, 109521827,1,2655,1832,1,
94593713,16,0,624,1, 109532657,3879,16,0,549,
9460299,3714,16,0,624, 109541,2550,1843,1,2579,
94611,52,3715,16,0, 109551861,1,2558,1849,1,
9462624,1,2318,3716,16, 109562566,1855,1,2459,1004,
94630,624,1,62,3717, 109571,2464,1021,1,2574,
946416,0,624,1,2075, 109581837,1,2470,3880,16,
94653718,16,0,624,1, 109590,549,1,2700,3881,
94661574,799,1,71,3719, 1096016,0,549,1,2594,
946716,0,624,1,76, 109611868,1,2596,3882,16,
94683720,16,0,624,1, 109620,549,1,80,3883,
94691834,3721,16,0,624, 1096319,426,1,80,3884,
94701,2337,3722,16,0, 109645,30,1,2644,1753,
9471624,1,79,3723,16, 109651,2520,1758,1,2639,
94720,624,1,1335,3724, 109661765,1,2640,1770,1,
947316,0,624,1,322, 109672641,1775,1,2642,1780,
94743725,16,0,624,1, 109681,2643,1747,1,2535,
947585,3726,16,0,624, 109691785,1,2645,1791,1,
94761,89,3727,16,0, 109702646,1796,1,2648,1875,
9477624,1,346,3728,16, 109711,2649,1802,1,2650,
94780,624,1,2105,814, 109721807,1,2651,1812,1,
94791,2106,3729,16,0, 109732652,1817,1,2653,1822,
9480624,1,97,3730,16, 109741,2654,1827,1,2655,
94810,624,1,1860,821, 109751832,1,2657,3885,16,
94821,2364,827,1,102, 109760,424,1,2550,1843,
94833731,16,0,624,1, 109771,2579,1861,1,2558,
9484112,3732,16,0,624, 109781849,1,2566,1855,1,
94851,1117,3733,16,0, 109792459,1004,1,2464,1021,
9486624,1,1873,835,1, 109801,2574,1837,1,2470,
94871876,3734,16,0,624, 109813886,16,0,424,1,
94881,124,3735,16,0, 109822700,3887,16,0,424,
9489624,1,2136,842,1, 109831,2594,1868,1,2596,
9490381,3736,16,0,624, 109843888,16,0,424,1,
94911,525,3737,16,0, 1098581,3889,19,413,1,
9492624,1,137,3738,16, 1098681,3890,5,30,1,
94930,624,1,1901,3739, 109872644,1753,1,2520,1758,
949416,0,624,1,2658, 109881,2639,1765,1,2640,
94953740,16,0,624,1, 109891770,1,2641,1775,1,
94961153,3741,16,0,624, 109902642,1780,1,2643,1747,
94971,151,3742,16,0, 109911,2535,1785,1,2645,
9498624,1,1407,3743,16, 109921791,1,2646,1796,1,
94990,624,1,1659,3744, 109932648,1875,1,2649,1802,
950016,0,624,1,2413, 109941,2650,1807,1,2651,
95013745,16,0,624,1, 109951812,1,2652,1817,1,
9502406,3746,16,0,624, 109962653,1822,1,2654,1827,
95031,1371,3747,16,0, 109971,2655,1832,1,2657,
9504624,1,166,3748,16, 109983891,16,0,411,1,
95050,624,1,1622,3749, 109992550,1843,1,2579,1861,
950616,0,624,1,1931, 110001,2558,1849,1,2566,
9507861,1,1933,3750,16, 110011855,1,2459,1004,1,
95080,624,1,431,3751, 110022464,1021,1,2574,1837,
950916,0,624,1,1585, 110031,2470,3892,16,0,
95103752,16,0,624,1, 11004411,1,2700,3893,16,
9511182,3753,16,0,624, 110050,411,1,2594,1868,
95121,1189,3754,16,0, 110061,2596,3894,16,0,
9513624,1,1443,3755,16, 11007411,1,82,3895,19,
95140,624,1,1695,3756, 11008758,1,82,3896,5,
951516,0,624,1,2198, 1100930,1,2644,1753,1,
95163757,16,0,624,1, 110102520,1758,1,2639,1765,
9517447,3758,16,0,624, 110111,2640,1770,1,2641,
95181,2458,876,1,2459, 110121775,1,2642,1780,1,
9519882,1,1958,3759,16, 110132643,1747,1,2535,1785,
95200,624,1,2462,889, 110141,2645,1791,1,2646,
95211,1657,894,1,2464, 110151796,1,2648,1875,1,
9522899,1,199,3760,16, 110162649,1802,1,2650,1807,
95230,624,1,459,3761, 110171,2651,1812,1,2652,
110181817,1,2653,1822,1,
110192654,1827,1,2655,1832,
110201,2657,3897,16,0,
11021756,1,2550,1843,1,
110222579,1861,1,2558,1849,
110231,2566,1855,1,2459,
110241004,1,2464,1021,1,
110252574,1837,1,2470,3898,
1102616,0,756,1,2700,
110273899,16,0,756,1,
110282594,1868,1,2596,3900,
1102916,0,756,1,83,
110303901,19,410,1,83,
110313902,5,30,1,2644,
110321753,1,2520,1758,1,
110332639,1765,1,2640,1770,
110341,2641,1775,1,2642,
110351780,1,2643,1747,1,
110362535,1785,1,2645,1791,
110371,2646,1796,1,2648,
110381875,1,2649,1802,1,
110392650,1807,1,2651,1812,
110401,2652,1817,1,2653,
110411822,1,2654,1827,1,
110422655,1832,1,2657,3903,
1104316,0,408,1,2550,
110441843,1,2579,1861,1,
110452558,1849,1,2566,1855,
110461,2459,1004,1,2464,
110471021,1,2574,1837,1,
110482470,3904,16,0,408,
110491,2700,3905,16,0,
11050408,1,2594,1868,1,
110512596,3906,16,0,408,
110521,84,3907,19,407,
110531,84,3908,5,30,
110541,2644,1753,1,2520,
110551758,1,2639,1765,1,
110562640,1770,1,2641,1775,
110571,2642,1780,1,2643,
110581747,1,2535,1785,1,
110592645,1791,1,2646,1796,
110601,2648,1875,1,2649,
110611802,1,2650,1807,1,
110622651,1812,1,2652,1817,
110631,2653,1822,1,2654,
110641827,1,2655,1832,1,
110652657,3909,16,0,405,
110661,2550,1843,1,2579,
110671861,1,2558,1849,1,
110682566,1855,1,2459,1004,
110691,2464,1021,1,2574,
110701837,1,2470,3910,16,
110710,405,1,2700,3911,
1107216,0,405,1,2594,
110731868,1,2596,3912,16,
110740,405,1,85,3913,
1107519,570,1,85,3914,
110765,30,1,2644,1753,
110771,2520,1758,1,2639,
110781765,1,2640,1770,1,
110792641,1775,1,2642,1780,
110801,2643,1747,1,2535,
110811785,1,2645,1791,1,
110822646,1796,1,2648,1875,
110831,2649,1802,1,2650,
110841807,1,2651,1812,1,
110852652,1817,1,2653,1822,
110861,2654,1827,1,2655,
110871832,1,2657,3915,16,
110880,568,1,2550,1843,
110891,2579,1861,1,2558,
110901849,1,2566,1855,1,
110912459,1004,1,2464,1021,
110921,2574,1837,1,2470,
110933916,16,0,568,1,
110942700,3917,16,0,568,
110951,2594,1868,1,2596,
110963918,16,0,568,1,
1109786,3919,19,442,1,
1109886,3920,5,30,1,
110992644,1753,1,2520,1758,
111001,2639,1765,1,2640,
111011770,1,2641,1775,1,
111022642,1780,1,2643,1747,
111031,2535,1785,1,2645,
111041791,1,2646,1796,1,
111052648,1875,1,2649,1802,
111061,2650,1807,1,2651,
111071812,1,2652,1817,1,
111082653,1822,1,2654,1827,
111091,2655,1832,1,2657,
111103921,16,0,440,1,
111112550,1843,1,2579,1861,
111121,2558,1849,1,2566,
111131855,1,2459,1004,1,
111142464,1021,1,2574,1837,
111151,2470,3922,16,0,
11116440,1,2700,3923,16,
111170,440,1,2594,1868,
111181,2596,3924,16,0,
11119440,1,87,3925,19,
11120548,1,87,3926,5,
1112130,1,2644,1753,1,
111222520,1758,1,2639,1765,
111231,2640,1770,1,2641,
111241775,1,2642,1780,1,
111252643,1747,1,2535,1785,
111261,2645,1791,1,2646,
111271796,1,2648,1875,1,
111282649,1802,1,2650,1807,
111291,2651,1812,1,2652,
111301817,1,2653,1822,1,
111312654,1827,1,2655,1832,
111321,2657,3927,16,0,
11133546,1,2550,1843,1,
111342579,1861,1,2558,1849,
111351,2566,1855,1,2459,
111361004,1,2464,1021,1,
111372574,1837,1,2470,3928,
1113816,0,546,1,2700,
111393929,16,0,546,1,
111402594,1868,1,2596,3930,
1114116,0,546,1,88,
111423931,19,404,1,88,
111433932,5,30,1,2644,
111441753,1,2520,1758,1,
111452639,1765,1,2640,1770,
111461,2641,1775,1,2642,
111471780,1,2643,1747,1,
111482535,1785,1,2645,1791,
111491,2646,1796,1,2648,
111501875,1,2649,1802,1,
111512650,1807,1,2651,1812,
111521,2652,1817,1,2653,
111531822,1,2654,1827,1,
111542655,1832,1,2657,3933,
1115516,0,402,1,2550,
111561843,1,2579,1861,1,
111572558,1849,1,2566,1855,
111581,2459,1004,1,2464,
111591021,1,2574,1837,1,
111602470,3934,16,0,402,
111611,2700,3935,16,0,
11162402,1,2594,1868,1,
111632596,3936,16,0,402,
111641,89,3937,19,398,
111651,89,3938,5,30,
111661,2644,1753,1,2520,
111671758,1,2639,1765,1,
111682640,1770,1,2641,1775,
111691,2642,1780,1,2643,
111701747,1,2535,1785,1,
111712645,1791,1,2646,1796,
111721,2648,1875,1,2649,
111731802,1,2650,1807,1,
111742651,1812,1,2652,1817,
111751,2653,1822,1,2654,
111761827,1,2655,1832,1,
111772657,3939,16,0,396,
111781,2550,1843,1,2579,
111791861,1,2558,1849,1,
111802566,1855,1,2459,1004,
111811,2464,1021,1,2574,
111821837,1,2470,3940,16,
111830,396,1,2700,3941,
1118416,0,396,1,2594,
111851868,1,2596,3942,16,
111860,396,1,90,3943,
1118719,401,1,90,3944,
111885,30,1,2644,1753,
111891,2520,1758,1,2639,
111901765,1,2640,1770,1,
111912641,1775,1,2642,1780,
111921,2643,1747,1,2535,
111931785,1,2645,1791,1,
111942646,1796,1,2648,1875,
111951,2649,1802,1,2650,
111961807,1,2651,1812,1,
111972652,1817,1,2653,1822,
111981,2654,1827,1,2655,
111991832,1,2657,3945,16,
112000,399,1,2550,1843,
112011,2579,1861,1,2558,
112021849,1,2566,1855,1,
112032459,1004,1,2464,1021,
112041,2574,1837,1,2470,
112053946,16,0,399,1,
112062700,3947,16,0,399,
112071,2594,1868,1,2596,
112083948,16,0,399,1,
1120991,3949,19,446,1,
1121091,3950,5,30,1,
112112644,1753,1,2520,1758,
112121,2639,1765,1,2640,
112131770,1,2641,1775,1,
112142642,1780,1,2643,1747,
112151,2535,1785,1,2645,
112161791,1,2646,1796,1,
112172648,1875,1,2649,1802,
112181,2650,1807,1,2651,
112191812,1,2652,1817,1,
112202653,1822,1,2654,1827,
112211,2655,1832,1,2657,
112223951,16,0,444,1,
112232550,1843,1,2579,1861,
112241,2558,1849,1,2566,
112251855,1,2459,1004,1,
112262464,1021,1,2574,1837,
112271,2470,3952,16,0,
11228444,1,2700,3953,16,
112290,444,1,2594,1868,
112301,2596,3954,16,0,
11231444,1,92,3955,19,
11232133,1,92,3956,5,
11233129,1,0,3957,16,
112340,314,1,1,2236,
112351,2,2242,1,3,
112362247,1,4,2252,1,
112375,2257,1,6,2262,
112381,7,2267,1,8,
112393958,16,0,131,1,
112401515,3959,16,0,184,
112411,2021,840,1,2022,
112423960,16,0,575,1,
11243256,3961,16,0,192,
112441,2526,3962,16,0,
11245300,1,2025,3963,16,
112460,579,1,18,3964,
1124716,0,138,1,2027,
112483965,16,0,583,1,
112492029,847,1,2030,853,
112501,2031,858,1,2032,
11251863,1,2033,868,1,
11252277,3966,16,0,192,
112531,2035,874,1,2037,
11254879,1,2541,3967,16,
112550,512,1,32,3968,
1125616,0,184,1,2041,
11257890,1,2293,3969,16,
112580,192,1,2043,896,
112591,2045,901,1,41,
112603970,16,0,192,1,
112611297,3971,16,0,184,
112621,43,3972,16,0,
11263192,1,46,3973,16,
112640,197,1,1804,3974,
1126516,0,184,1,299,
112663975,16,0,192,1,
1126752,3976,16,0,184,
112681,2818,3516,1,2819,
112693977,16,0,314,1,
112702318,3978,16,0,184,
112711,62,3979,16,0,
11272221,1,65,3980,16,
112730,223,1,2075,3981,
1127416,0,184,1,1574,
11275921,1,71,3982,16,
112760,192,1,1775,3983,
1127716,0,184,1,2837,
112783530,1,2838,3536,1,
112792337,3984,16,0,184,
112801,79,3985,16,0,
11281192,1,1335,3986,16,
112820,184,1,2511,3987,
1128316,0,477,1,322,
112843988,16,0,192,1,
1128576,3989,16,0,192,
112861,85,3990,16,0,
11287192,1,1261,3991,16,
112880,184,1,89,3992,
1128916,0,192,1,509,
112903993,16,0,192,1,
11291346,3994,16,0,192,
112921,2039,884,1,97,
112933995,16,0,192,1,
112942106,3996,16,0,184,
112951,102,3997,16,0,
11296192,1,1860,943,1,
112971803,909,1,2364,949,
112981,2779,3510,1,2782,
112993998,16,0,192,1,
11300112,3999,16,0,192,
113011,1117,4000,16,0,
11302184,1,1873,958,1,
113031876,4001,16,0,184,
113041,372,4002,16,0,
11305613,1,374,4003,16,
113060,615,1,124,4004,
1130716,0,192,1,376,
113084005,16,0,617,1,
11309378,4006,16,0,619,
113101,2136,965,1,381,
113114007,16,0,192,1,
11312525,4008,16,0,192,
113131,2807,3551,1,1834,
113144009,16,0,184,1,
11315137,4010,16,0,192,
113161,1901,4011,16,0,
11317184,1,1113,4012,16,
113180,176,1,1153,4013,
1131916,0,184,1,151,
113204014,16,0,192,1,
113211407,4015,16,0,184,
113221,1659,4016,16,0,
11323184,1,2413,4017,16,
113240,184,1,406,4018,
1132516,0,192,1,1371,
113264019,16,0,184,1,
113272105,936,1,166,4020,
1132816,0,192,1,2839,
113293541,1,2840,3546,1,
113301931,983,1,1933,4021,
1133116,0,184,1,431,
113324022,16,0,192,1,
113331585,4023,16,0,192,
113341,182,4024,16,0,
11335192,1,1189,4025,16,
113360,184,1,1443,4026,
1133716,0,184,1,1695,
113384027,16,0,184,1,
113392198,4028,16,0,184,
113401,447,4029,16,0,
11341192,1,2458,998,1,
113422459,1004,1,1958,4030,
1134316,0,184,1,2462,
113441011,1,1657,1016,1,
113452464,1021,1,2466,3525,
113461,459,4031,16,0,
11347192,1,2468,4032,16,
113480,376,1,462,4033,
1134916,0,192,1,199,
113504034,16,0,192,1,
11351217,4035,16,0,192,
113521,2227,1030,1,1622,
113534036,16,0,192,1,
113541225,4037,16,0,184,
113551,1479,4038,16,0,
11356184,1,1731,4039,16,
113570,192,1,1989,1038,
113581,1990,4040,16,0,
11359184,1,236,4041,16,
113600,192,1,2507,4042,
1136116,0,471,1,1756,
113624043,16,0,184,1,
1136393,4044,19,731,1,
1136493,4045,5,95,1,
11365256,4046,16,0,729,
113661,1261,4047,16,0,
11367729,1,509,4048,16,
113680,729,1,1515,4049,
1136916,0,729,1,2021,
11370840,1,1775,4050,16,
113710,729,1,2029,847,
113721,2030,853,1,2031,
11373858,1,2032,863,1,
113742033,868,1,277,4051,
1137516,0,729,1,2035,
11376874,1,2037,879,1,
113772039,884,1,32,4052,
1137816,0,729,1,2041,
11379890,1,2293,4053,16,
113800,729,1,2043,896,
113811,2045,901,1,41,
113824054,16,0,729,1,
113831297,4055,16,0,729,
113841,43,4056,16,0,
11385729,1,1803,909,1,
113861804,4057,16,0,729,
113871,299,4058,16,0,
11388729,1,52,4059,16,
113890,729,1,2318,4060,
1139016,0,729,1,62,
113914061,16,0,729,1,
113922075,4062,16,0,729,
113931,1574,921,1,71,
113944063,16,0,729,1,
1139576,4064,16,0,729,
113961,1834,4065,16,0,
11397729,1,2337,4066,16,
113980,729,1,79,4067,
1139916,0,729,1,1335,
114004068,16,0,729,1,
11401322,4069,16,0,729,
114021,85,4070,16,0,
11403729,1,89,4071,16,
114040,729,1,346,4072,
1140516,0,729,1,2105,
11406936,1,2106,4073,16,
114070,729,1,97,4074,
1140816,0,729,1,1860,
11409943,1,2364,949,1,
11410102,4075,16,0,729,
114111,2782,4076,16,0,
11412729,1,112,4077,16,
114130,729,1,1117,4078,
1141416,0,729,1,1873,
11415958,1,1876,4079,16,
114160,729,1,124,4080,
1141716,0,729,1,2136,
11418965,1,381,4081,16,
114190,729,1,525,4082,
1142016,0,729,1,137,
114214083,16,0,729,1,
114221901,4084,16,0,729,
114231,1153,4085,16,0,
11424729,1,151,4086,16,
114250,729,1,1407,4087,
1142616,0,729,1,1659,
114274088,16,0,729,1,
114282413,4089,16,0,729,
114291,406,4090,16,0,
11430729,1,1371,4091,16,
114310,729,1,166,4092,
1143216,0,729,1,1622,
114334093,16,0,729,1,
114341931,983,1,1933,4094,
1143516,0,729,1,431,
114364095,16,0,729,1,
114371585,4096,16,0,729,
114381,182,4097,16,0,
11439729,1,1189,4098,16,
114400,729,1,1443,4099,
1144116,0,729,1,1695,
114424100,16,0,729,1,
114432198,4101,16,0,729,
114441,447,4102,16,0,
11445729,1,2458,998,1,
114462459,1004,1,1958,4103,
1144716,0,729,1,2462,
114481011,1,1657,1016,1,
114492464,1021,1,199,4104,
1145016,0,729,1,459,
114514105,16,0,729,1,
11452462,4106,16,0,729,
114531,217,4107,16,0,
11454729,1,2227,1030,1,
114551225,4108,16,0,729,
114561,1479,4109,16,0,
11457729,1,1731,4110,16,
114580,729,1,1989,1038,
114591,1990,4111,16,0,
11460729,1,236,4112,16,
114610,729,1,1756,4113,
1146216,0,729,1,94,
114634114,19,728,1,94,
114644115,5,95,1,256,
114654116,16,0,726,1,
114661261,4117,16,0,726,
114671,509,4118,16,0,
11468726,1,1515,4119,16,
114690,726,1,2021,840,
114701,1775,4120,16,0,
11471726,1,2029,847,1,
114722030,853,1,2031,858,
114731,2032,863,1,2033,
11474868,1,277,4121,16,
114750,726,1,2035,874,
114761,2037,879,1,2039,
11477884,1,32,4122,16,
114780,726,1,2041,890,
114791,2293,4123,16,0,
11480726,1,2043,896,1,
114812045,901,1,41,4124,
1148216,0,726,1,1297,
114834125,16,0,726,1,
1148443,4126,16,0,726,
114851,1803,909,1,1804,
114864127,16,0,726,1,
11487299,4128,16,0,726,
114881,52,4129,16,0,
11489726,1,2318,4130,16,
114900,726,1,62,4131,
1149116,0,726,1,2075,
114924132,16,0,726,1,
114931574,921,1,71,4133,
1149416,0,726,1,76,
114954134,16,0,726,1,
114961834,4135,16,0,726,
114971,2337,4136,16,0,
11498726,1,79,4137,16,
114990,726,1,1335,4138,
1150016,0,726,1,322,
115014139,16,0,726,1,
1150285,4140,16,0,726,
115031,89,4141,16,0,
11504726,1,346,4142,16,
115050,726,1,2105,936,
115061,2106,4143,16,0,
11507726,1,97,4144,16,
115080,726,1,1860,943,
115091,2364,949,1,102,
115104145,16,0,726,1,
115112782,4146,16,0,726,
115121,112,4147,16,0,
11513726,1,1117,4148,16,
115140,726,1,1873,958,
115151,1876,4149,16,0,
11516726,1,124,4150,16,
115170,726,1,2136,965,
115181,381,4151,16,0,
11519726,1,525,4152,16,
115200,726,1,137,4153,
1152116,0,726,1,1901,
115224154,16,0,726,1,
115231153,4155,16,0,726,
115241,151,4156,16,0,
11525726,1,1407,4157,16,
115260,726,1,1659,4158,
1152716,0,726,1,2413,
115284159,16,0,726,1,
11529406,4160,16,0,726,
115301,1371,4161,16,0,
11531726,1,166,4162,16,
115320,726,1,1622,4163,
1153316,0,726,1,1931,
11534983,1,1933,4164,16,
115350,726,1,431,4165,
1153616,0,726,1,1585,
115374166,16,0,726,1,
11538182,4167,16,0,726,
115391,1189,4168,16,0,
11540726,1,1443,4169,16,
115410,726,1,1695,4170,
1154216,0,726,1,2198,
115434171,16,0,726,1,
11544447,4172,16,0,726,
115451,2458,998,1,2459,
115461004,1,1958,4173,16,
115470,726,1,2462,1011,
115481,1657,1016,1,2464,
115491021,1,199,4174,16,
115500,726,1,459,4175,
1155116,0,726,1,462,
115524176,16,0,726,1,
11553217,4177,16,0,726,
115541,2227,1030,1,1225,
115554178,16,0,726,1,
115561479,4179,16,0,726,
115571,1731,4180,16,0,
11558726,1,1989,1038,1,
115591990,4181,16,0,726,
115601,236,4182,16,0,
11561726,1,1756,4183,16,
115620,726,1,95,4184,
1156319,725,1,95,4185,
115645,95,1,256,4186,
1156516,0,723,1,1261,
115664187,16,0,723,1,
11567509,4188,16,0,723,
115681,1515,4189,16,0,
11569723,1,2021,840,1,
115701775,4190,16,0,723,
115711,2029,847,1,2030,
11572853,1,2031,858,1,
115732032,863,1,2033,868,
115741,277,4191,16,0,
11575723,1,2035,874,1,
115762037,879,1,2039,884,
115771,32,4192,16,0,
11578723,1,2041,890,1,
115792293,4193,16,0,723,
115801,2043,896,1,2045,
11581901,1,41,4194,16,
115820,723,1,1297,4195,
1158316,0,723,1,43,
115844196,16,0,723,1,
115851803,909,1,1804,4197,
1158616,0,723,1,299,
115874198,16,0,723,1,
1158852,4199,16,0,723,
115891,2318,4200,16,0,
11590723,1,62,4201,16,
115910,723,1,2075,4202,
1159216,0,723,1,1574,
11593921,1,71,4203,16,
115940,723,1,76,4204,
1159516,0,723,1,1834,
115964205,16,0,723,1,
115972337,4206,16,0,723,
115981,79,4207,16,0,
11599723,1,1335,4208,16,
116000,723,1,322,4209,
1160116,0,723,1,85,
116024210,16,0,723,1,
1160389,4211,16,0,723,
116041,346,4212,16,0,
11605723,1,2105,936,1,
116062106,4213,16,0,723,
116071,97,4214,16,0,
11608723,1,1860,943,1,
116092364,949,1,102,4215,
1161016,0,723,1,2782,
116114216,16,0,723,1,
11612112,4217,16,0,723,
116131,1117,4218,16,0,
11614723,1,1873,958,1,
116151876,4219,16,0,723,
116161,124,4220,16,0,
11617723,1,2136,965,1,
11618381,4221,16,0,723,
116191,525,4222,16,0,
11620723,1,137,4223,16,
116210,723,1,1901,4224,
1162216,0,723,1,1153,
116234225,16,0,723,1,
11624151,4226,16,0,723,
116251,1407,4227,16,0,
11626723,1,1659,4228,16,
116270,723,1,2413,4229,
1162816,0,723,1,406,
116294230,16,0,723,1,
116301371,4231,16,0,723,
116311,166,4232,16,0,
11632723,1,1622,4233,16,
116330,723,1,1931,983,
116341,1933,4234,16,0,
11635723,1,431,4235,16,
116360,723,1,1585,4236,
1163716,0,723,1,182,
116384237,16,0,723,1,
116391189,4238,16,0,723,
116401,1443,4239,16,0,
11641723,1,1695,4240,16,
116420,723,1,2198,4241,
1164316,0,723,1,447,
116444242,16,0,723,1,
116452458,998,1,2459,1004,
116461,1958,4243,16,0,
11647723,1,2462,1011,1,
116481657,1016,1,2464,1021,
116491,199,4244,16,0,
11650723,1,459,4245,16,
116510,723,1,462,4246,
1165216,0,723,1,217,
116534247,16,0,723,1,
116542227,1030,1,1225,4248,
1165516,0,723,1,1479,
116564249,16,0,723,1,
116571731,4250,16,0,723,
116581,1989,1038,1,1990,
116594251,16,0,723,1,
11660236,4252,16,0,723,
116611,1756,4253,16,0,
11662723,1,96,4254,19,
11663103,1,96,4255,5,
116641,1,0,4256,16,
116650,104,1,97,4257,
1166619,172,1,97,4258,
116675,1,1,0,4259,
1166816,0,170,1,98,
116694260,19,213,1,98,
116704261,5,2,1,0,
116714262,16,0,211,1,
116722819,4263,16,0,366,
116731,99,4264,19,210,
116741,99,4265,5,2,
116751,0,4266,16,0,
11676208,1,2819,4267,16,
116770,365,1,100,4268,
1167819,292,1,100,4269,
116795,2,1,0,4270,
1168016,0,775,1,2819,
116814271,16,0,290,1,
11682101,4272,19,781,1,
11683101,4273,5,4,1,
116840,4274,16,0,782,
116851,2830,4275,16,0,
11686779,1,2819,4276,16,
116870,782,1,2760,4277,
1168816,0,779,1,102,
116894278,19,698,1,102,
116904279,5,2,1,2470,
116914280,16,0,696,1,
116922657,4281,16,0,719,
116931,103,4282,19,157,
116941,103,4283,5,4,
116951,2596,4284,16,0,
11696155,1,2470,4285,16,
116970,674,1,2700,4286,
1169816,0,155,1,2657,
116994287,16,0,674,1,
11700104,4288,19,154,1,
11701104,4289,5,4,1,
117022596,4290,16,0,152,
117031,2470,4291,16,0,
11704177,1,2700,4292,16,
117050,152,1,2657,4293,
1170616,0,177,1,105,
117074294,19,657,1,105,
117084295,5,4,1,2596,
117094296,16,0,655,1,
117102470,4297,16,0,672,
117111,2700,4298,16,0,
11712655,1,2657,4299,16,
117130,672,1,106,4300,
1171419,175,1,106,4301,
117155,4,1,2596,4302,
1171616,0,654,1,2470,
117174303,16,0,173,1,
117182700,4304,16,0,654,
117191,2657,4305,16,0,
11720173,1,107,4306,19,
11721670,1,107,4307,5,
117224,1,2596,4308,16,
117230,742,1,2470,4309,
1172416,0,668,1,2700,
117254310,16,0,742,1,
117262657,4311,16,0,668,
117271,108,4312,19,169,
117281,108,4313,5,4,
117291,2596,4314,16,0,
11730650,1,2470,4315,16,
117310,167,1,2700,4316,
1173216,0,650,1,2657,
117334317,16,0,167,1,
11734109,4318,19,741,1,
11735109,4319,5,4,1,
117362596,4320,16,0,739,
117371,2470,4321,16,0,
11738751,1,2700,4322,16,
117390,739,1,2657,4323,
1174016,0,751,1,110,
117414324,19,648,1,110,
117424325,5,4,1,2596,
117434326,16,0,646,1,
117442470,4327,16,0,663,
117451,2700,4328,16,0,
11746646,1,2657,4329,16,
117470,663,1,111,4330,
1174819,141,1,111,4331,
117495,3,1,2766,4332,
1175016,0,791,1,2581,
117514333,16,0,355,1,
1175210,4334,16,0,139,
117531,112,4335,19,557,
117541,112,4336,5,1,
117551,2568,4337,16,0,
11756555,1,113,4338,19,
11757745,1,113,4339,5,
117581,1,2560,4340,16,
117590,743,1,114,4341,
1176019,529,1,114,4342,
117615,1,1,2552,4343,
1176216,0,527,1,115,
117634344,19,251,1,115,
117644345,5,1,1,2537,
117654346,16,0,249,1,
11766116,4347,19,502,1,
11767116,4348,5,1,1,
117682522,4349,16,0,500,
117691,117,4350,19,486,
117701,117,4351,5,1,
117711,2506,4352,16,0,
11772484,1,118,4353,19,
11773160,1,118,4354,5,
1177417,1,0,4355,16,
117750,794,1,2581,4356,
1177616,0,372,1,2075,
117774357,16,0,753,1,
117782337,4358,16,0,753,
117791,2819,4359,16,0,
11780794,1,2413,4360,16,
117810,753,1,10,4361,
1178216,0,372,1,1901,
117834362,16,0,753,1,
117842198,4363,16,0,753,
117851,21,4364,16,0,
11786158,1,2106,4365,16,
117870,753,1,2766,4366,
1178816,0,372,1,1804,
117894367,16,0,753,1,
117901990,4368,16,0,753,
117911,32,4369,16,0,
11792753,1,1958,4370,16,
117930,753,1,1775,4371,
1179416,0,753,1,119,
117954372,19,474,1,119,
117964373,5,2,1,2568,
117974374,16,0,671,1,
117982506,4375,16,0,472,
117991,120,4376,19,480,
118001,120,4377,5,5,
118011,2510,4378,16,0,
11802478,1,2522,4379,16,
118030,491,1,2514,4380,
1180416,0,483,1,2537,
118054381,16,0,509,1,
118062560,4382,16,0,537,
118071,121,4383,19,309,
118081,121,4384,5,3,
118091,2552,4385,16,0,
11810737,1,2525,4386,16,
118110,307,1,2529,4387,
1181216,0,499,1,122,
118134388,19,636,1,122,
118144389,5,2,1,2544,
118154390,16,0,637,1,
118162540,4391,16,0,634,
118171,123,4392,19,130,
118181,123,4393,5,18,
118191,0,4394,16,0,
11820128,1,2581,4395,16,
118210,137,1,2075,4396,
1182216,0,137,1,2337,
118234397,16,0,137,1,
118242819,4398,16,0,128,
118251,2413,4399,16,0,
11826137,1,10,4400,16,
118270,137,1,2198,4401,
1182816,0,137,1,1901,
118294402,16,0,137,1,
1183052,4403,16,0,219,
118311,21,4404,16,0,
11832137,1,2106,4405,16,
118330,137,1,2766,4406,
1183416,0,137,1,1804,
118354407,16,0,137,1,
118361990,4408,16,0,137,
118371,32,4409,16,0,
11838137,1,1958,4410,16,
118390,137,1,1775,4411,
1184016,0,137,1,124,
118414412,19,765,1,124,
118424413,5,4,1,2596,
118434414,16,0,763,1,
118442470,4415,16,0,763,
118451,2700,4416,16,0,
11846763,1,2657,4417,16,
118470,763,1,125,4418,
1184819,567,1,125,4419,
118495,4,1,2596,4420,
1185016,0,565,1,2470,
118514421,16,0,565,1,
118522700,4422,16,0,565,
118531,2657,4423,16,0,
11854565,1,126,4424,19,
11855666,1,126,4425,5,
118564,1,2596,4426,16,
118570,664,1,2470,4427,
1185816,0,664,1,2700,
118594428,16,0,664,1,
118602657,4429,16,0,664,
118611,127,4430,19,535,
118621,127,4431,5,4,
118631,2596,4432,16,0,
11864533,1,2470,4433,16,
118650,533,1,2700,4434,
1186616,0,533,1,2657,
118674435,16,0,533,1,
11868128,4436,19,524,1,
11869128,4437,5,4,1,
118702596,4438,16,0,522,
118711,2470,4439,16,0,
11872522,1,2700,4440,16,
118730,522,1,2657,4441,
1187416,0,522,1,129,
118754442,19,632,1,129,
118764443,5,4,1,2596,
118774444,16,0,630,1,
118782470,4445,16,0,630,
118791,2700,4446,16,0,
11880630,1,2657,4447,16,
118810,630,1,130,4448,
1188219,778,1,130,4449,
118835,4,1,2596,4450,
1188416,0,776,1,2470,
118854451,16,0,776,1,
118862700,4452,16,0,776,
118871,2657,4453,16,0,
11888776,1,131,4454,19,
11889768,1,131,4455,5,
118904,1,2596,4456,16,
118910,766,1,2470,4457,
1189216,0,766,1,2700,
118934458,16,0,766,1,
118942657,4459,16,0,766,
118951,132,4460,19,328,
118961,132,4461,5,21,
118971,2518,4462,16,0,
11898699,1,2075,4463,16,
118990,584,1,2548,4464,
1190016,0,736,1,2337,
119014465,16,0,584,1,
119022413,4466,16,0,584,
119031,2564,4467,16,0,
11904542,1,2556,4468,16,
119050,532,1,2592,4469,
1190616,0,695,1,1901,
119074470,16,0,584,1,
119082198,4471,16,0,584,
119091,2533,4472,16,0,
11910504,1,2777,4473,16,
119110,326,1,2572,4474,
1191216,0,675,1,2106,
119134475,16,0,584,1,
119142577,4476,16,0,681,
119151,1804,4477,16,0,
11916584,1,1990,4478,16,
119170,584,1,31,4479,
1191816,0,371,1,32,
119194480,16,0,584,1,
119201958,4481,16,0,584,
119211,1775,4482,16,0,
11922584,1,133,4483,19,
11923337,1,133,4484,5,
119241,1,32,4485,16,
119250,335,1,134,4486,
1192619,286,1,134,4487,
119275,11,1,2075,4488,
1192816,0,682,1,2337,
119294489,16,0,293,1,
119302413,4490,16,0,505,
119311,1901,4491,16,0,
11932427,1,2198,4492,16,
119330,354,1,2106,4493,
1193416,0,715,1,1804,
119354494,16,0,317,1,
119361990,4495,16,0,572,
119371,32,4496,16,0,
11938367,1,1958,4497,16,
119390,515,1,1775,4498,
1194016,0,284,1,135,
119414499,19,688,1,135,
119424500,5,11,1,2075,
119434501,16,0,686,1,
119442337,4502,16,0,686,
119451,2413,4503,16,0,
11946686,1,1901,4504,16,
119470,686,1,2198,4505,
1194816,0,686,1,2106,
119494506,16,0,686,1,
119501804,4507,16,0,686,
119511,1990,4508,16,0,
11952686,1,32,4509,16,
119530,686,1,1958,4510,
1195416,0,686,1,1775,
119554511,16,0,686,1,
11956136,4512,19,748,1,
11957136,4513,5,11,1,
119582075,4514,16,0,746,
119591,2337,4515,16,0,
11960746,1,2413,4516,16,
119610,746,1,1901,4517,
1196216,0,746,1,2198,
119634518,16,0,746,1,
119642106,4519,16,0,746,
119651,1804,4520,16,0,
11966746,1,1990,4521,16,
119670,746,1,32,4522,
1196816,0,746,1,1958,
119694523,16,0,746,1,
119701775,4524,16,0,746,
119711,137,4525,19,180,
119721,137,4526,5,31,
119731,1901,4527,16,0,
11974752,1,1479,4528,16,
119750,638,1,2075,4529,
1197616,0,752,1,1695,
119774530,16,0,217,1,
119781756,4531,16,0,207,
119791,2413,4532,16,0,
11980752,1,2198,4533,16,
119810,752,1,1876,4534,
1198216,0,771,1,1659,
119834535,16,0,207,1,
119841443,4536,16,0,600,
119851,1117,4537,16,0,
11986178,1,1990,4538,16,
119870,752,1,1189,4539,
1198816,0,267,1,1775,
119894540,16,0,752,1,
1199032,4541,16,0,752,
119911,2106,4542,16,0,
11992752,1,1515,4543,16,
119930,684,1,2337,4544,
1199416,0,752,1,52,
119954545,16,0,700,1,
119961804,4546,16,0,752,
119971,1261,4547,16,0,
11998331,1,1153,4548,16,
119990,274,1,1225,4549,
1200016,0,303,1,1335,
120014550,16,0,497,1,
120021933,4551,16,0,640,
120031,1834,4552,16,0,
12004347,1,1297,4553,16,
120050,359,1,1407,4554,
1200616,0,667,1,2318,
120074555,16,0,207,1,
120081958,4556,16,0,752,
120091,1371,4557,16,0,
12010488,1,138,4558,19,
12011609,1,138,4559,5,
1201211,1,2075,4560,16,
120130,607,1,2337,4561,
1201416,0,607,1,2413,
120154562,16,0,607,1,
120161901,4563,16,0,607,
120171,2198,4564,16,0,
12018607,1,2106,4565,16,
120190,607,1,1804,4566,
1202016,0,607,1,1990,
120214567,16,0,607,1,
1202232,4568,16,0,607,
120231,1958,4569,16,0,
12024607,1,1775,4570,16,
120250,607,1,139,4571,
1202619,605,1,139,4572,
120275,11,1,2075,4573,
1202816,0,603,1,2337,
120294574,16,0,603,1,
120302413,4575,16,0,603,
120311,1901,4576,16,0,
12032603,1,2198,4577,16,
120330,603,1,2106,4578,
1203416,0,603,1,1804,
120354579,16,0,603,1,
120361990,4580,16,0,603,
120371,32,4581,16,0,
12038603,1,1958,4582,16,
120390,603,1,1775,4583,
1204016,0,603,1,140,
120414584,19,679,1,140,
120424585,5,11,1,2075,
120434586,16,0,677,1,
120442337,4587,16,0,677,
120451,2413,4588,16,0,
12046677,1,1901,4589,16,
120470,677,1,2198,4590,
1204816,0,677,1,2106,
120494591,16,0,677,1,
120501804,4592,16,0,677,
120511,1990,4593,16,0,
12052677,1,32,4594,16,
120530,677,1,1958,4595,
1205416,0,677,1,1775,
120554596,16,0,677,1,
12056141,4597,19,599,1,
12057141,4598,5,11,1,
120582075,4599,16,0,597,
120591,2337,4600,16,0,
12060597,1,2413,4601,16,
120610,597,1,1901,4602,
1206216,0,597,1,2198,
120634603,16,0,597,1,
120642106,4604,16,0,597,
120651,1804,4605,16,0,
12066597,1,1990,4606,16,
120670,597,1,32,4607,
1206816,0,597,1,1958,
120694608,16,0,597,1,
120701775,4609,16,0,597,
120711,142,4610,19,596,
120721,142,4611,5,11,
120731,2075,4612,16,0,
12074594,1,2337,4613,16,
120750,594,1,2413,4614,
1207616,0,594,1,1901,
120774615,16,0,594,1,
120782198,4616,16,0,594,
120791,2106,4617,16,0,
12080594,1,1804,4618,16,
120810,594,1,1990,4619,
1208216,0,594,1,32,
120834620,16,0,594,1,
120841958,4621,16,0,594,
120851,1775,4622,16,0,
12086594,1,143,4623,19,
12087593,1,143,4624,5,
1208811,1,2075,4625,16,
120890,591,1,2337,4626,
1209016,0,591,1,2413,
120914627,16,0,591,1,
120921901,4628,16,0,591,
120931,2198,4629,16,0,
12094591,1,2106,4630,16,
120950,591,1,1804,4631,
1209616,0,591,1,1990,
120974632,16,0,591,1,
1209832,4633,16,0,591,
120991,1958,4634,16,0,
12100591,1,1775,4635,16,
121010,591,1,144,4636,
1210219,590,1,144,4637,
121035,11,1,2075,4638,
1210416,0,588,1,2337,
121054639,16,0,588,1,
121062413,4640,16,0,588,
121071,1901,4641,16,0,
12108588,1,2198,4642,16,
121090,588,1,2106,4643,
1211016,0,588,1,1804,
121114644,16,0,588,1,
121121990,4645,16,0,588,
121131,32,4646,16,0,
12114588,1,1958,4647,16,
121150,588,1,1775,4648,
1211616,0,588,1,145,
121174649,19,587,1,145,
121184650,5,11,1,2075,
121194651,16,0,585,1,
121202337,4652,16,0,585,
121211,2413,4653,16,0,
12122585,1,1901,4654,16,
121230,585,1,2198,4655,
1212416,0,585,1,2106,
121254656,16,0,585,1,
121261804,4657,16,0,585,
121271,1990,4658,16,0,
12128585,1,32,4659,16,
121290,585,1,1958,4660,
1213016,0,585,1,1775,
121314661,16,0,585,1,
12132146,4662,19,150,1,
12133146,4663,5,3,1,
121341756,4664,16,0,316,
121351,2318,4665,16,0,
12136330,1,1659,4666,16,
121370,148,1,147,4667,
1213819,626,1,147,4668,
121395,68,1,1901,4669,
1214016,0,624,1,1479,
121414670,16,0,624,1,
12142112,4671,16,0,624,
121431,2293,4672,16,0,
12144624,1,1804,4673,16,
121450,624,1,431,4674,
1214616,0,624,1,1443,
121474675,16,0,624,1,
121481756,4676,16,0,624,
121491,124,4677,16,0,
12150624,1,525,4678,16,
121510,624,1,236,4679,
1215216,0,624,1,346,
121534680,16,0,624,1,
121541876,4681,16,0,624,
121551,1659,4682,16,0,
12156624,1,1225,4683,16,
121570,624,1,1117,4684,
1215816,0,624,1,137,
121594685,16,0,624,1,
121602318,4686,16,0,624,
121611,1775,4687,16,0,
12162624,1,32,4688,16,
121630,624,1,1407,4689,
1216416,0,624,1,2782,
121654690,16,0,624,1,
12166256,4691,16,0,624,
121671,459,4692,16,0,
12168624,1,406,4693,16,
121690,624,1,41,4694,
1217016,0,624,1,151,
121714695,16,0,624,1,
1217243,4696,16,0,624,
121731,1585,4697,16,0,
12174624,1,1990,4698,16,
121750,624,1,2337,4699,
1217616,0,624,1,509,
121774700,16,0,624,1,
1217852,4701,16,0,624,
121791,381,4702,16,0,
12180624,1,447,4703,16,
121810,624,1,166,4704,
952416,0,624,1,462, 1218216,0,624,1,462,
95253762,16,0,624,1, 121834705,16,0,624,1,
9526217,3763,16,0,624, 12184277,4706,16,0,624,
95271,2227,908,1,1225, 121851,1695,4707,16,0,
95283764,16,0,624,1, 12186624,1,62,4708,16,
95291479,3765,16,0,624, 121870,692,1,1153,4709,
95301,1731,3766,16,0, 1218816,0,624,1,2106,
9531624,1,1989,916,1, 121894710,16,0,624,1,
95321990,3767,16,0,624, 121901335,4711,16,0,624,
95331,236,3768,16,0, 121911,71,4712,16,0,
9534624,1,1756,3769,16, 12192624,1,182,4713,16,
95350,624,1,94,3770, 121930,624,1,76,4714,
953619,623,1,94,3771, 1219416,0,624,1,79,
95375,95,1,256,3772, 121954715,16,0,624,1,
953816,0,621,1,1261, 121961933,4716,16,0,624,
95393773,16,0,621,1, 121971,299,4717,16,0,
9540509,3774,16,0,621, 12198624,1,85,4718,16,
95411,1515,3775,16,0, 121990,624,1,1515,4719,
9542621,1,2021,718,1, 1220016,0,624,1,2198,
95431775,3776,16,0,621, 122014720,16,0,624,1,
95441,2029,725,1,2030, 1220289,4721,16,0,624,
9545731,1,2031,736,1, 122031,1834,4722,16,0,
95462032,741,1,2033,746, 12204624,1,1622,4723,16,
95471,277,3777,16,0, 122050,624,1,2413,4724,
9548621,1,2035,752,1, 1220616,0,624,1,2075,
95492037,757,1,2039,762, 122074725,16,0,624,1,
95501,32,3778,16,0, 122081731,4726,16,0,624,
9551621,1,2041,768,1, 122091,97,4727,16,0,
95522293,3779,16,0,621, 12210624,1,1297,4728,16,
95531,2043,774,1,2045, 122110,624,1,1189,4729,
9554779,1,41,3780,16, 1221216,0,624,1,102,
95550,621,1,1297,3781, 122134730,16,0,624,1,
955616,0,621,1,43, 122141261,4731,16,0,624,
95573782,16,0,621,1, 122151,322,4732,16,0,
95581803,787,1,1804,3783, 12216624,1,1958,4733,16,
955916,0,621,1,299, 122170,624,1,199,4734,
95603784,16,0,621,1, 1221816,0,624,1,1371,
956152,3785,16,0,621, 122194735,16,0,624,1,
95621,2318,3786,16,0, 12220217,4736,16,0,624,
9563621,1,62,3787,16, 122211,148,4737,19,710,
95640,621,1,2075,3788, 122221,148,4738,5,2,
956516,0,621,1,1574, 122231,459,4739,16,0,
9566799,1,71,3789,16, 12224708,1,41,4740,16,
95670,621,1,76,3790, 122250,783,1,149,4741,
956816,0,621,1,1834, 1222619,714,1,149,4742,
95693791,16,0,621,1, 122275,3,1,462,4743,
95702337,3792,16,0,621, 1222816,0,712,1,459,
95711,79,3793,16,0, 122294744,16,0,735,1,
9572621,1,1335,3794,16, 1223041,4745,16,0,735,
95730,621,1,322,3795, 122311,150,4746,19,4747,
957416,0,621,1,85, 122324,36,69,0,120,
95753796,16,0,621,1, 122330,112,0,114,0,
957689,3797,16,0,621, 12234101,0,115,0,115,
95771,346,3798,16,0, 122350,105,0,111,0,
9578621,1,2105,814,1, 12236110,0,65,0,114,
95792106,3799,16,0,621, 122370,103,0,117,0,
95801,97,3800,16,0, 12238109,0,101,0,110,
9581621,1,1860,821,1, 122390,116,0,1,150,
95822364,827,1,102,3801, 122404742,1,151,4748,19,
958316,0,621,1,112, 12241622,1,151,4749,5,
95843802,16,0,621,1, 1224268,1,1901,4750,16,
95851117,3803,16,0,621, 122430,620,1,1479,4751,
95861,1873,835,1,1876, 1224416,0,620,1,112,
95873804,16,0,621,1, 122454752,16,0,620,1,
9588124,3805,16,0,621, 122462293,4753,16,0,620,
95891,2136,842,1,381, 122471,1804,4754,16,0,
95903806,16,0,621,1, 12248620,1,431,4755,16,
9591525,3807,16,0,621, 122490,620,1,1443,4756,
95921,137,3808,16,0, 1225016,0,620,1,1756,
9593621,1,1901,3809,16, 122514757,16,0,620,1,
95940,621,1,2658,3810, 12252124,4758,16,0,620,
959516,0,621,1,1153, 122531,525,4759,16,0,
95963811,16,0,621,1, 12254620,1,236,4760,16,
9597151,3812,16,0,621, 122550,620,1,346,4761,
95981,1407,3813,16,0, 1225616,0,620,1,1876,
9599621,1,1659,3814,16, 122574762,16,0,620,1,
96000,621,1,2413,3815, 122581659,4763,16,0,620,
960116,0,621,1,406, 122591,1225,4764,16,0,
96023816,16,0,621,1, 12260620,1,1117,4765,16,
96031371,3817,16,0,621, 122610,620,1,137,4766,
96041,166,3818,16,0, 1226216,0,620,1,2318,
9605621,1,1622,3819,16, 122634767,16,0,620,1,
96060,621,1,1931,861, 122641775,4768,16,0,620,
96071,1933,3820,16,0, 122651,32,4769,16,0,
9608621,1,431,3821,16, 12266620,1,1407,4770,16,
96090,621,1,1585,3822, 122670,620,1,2782,4771,
961016,0,621,1,182, 1226816,0,620,1,256,
96113823,16,0,621,1, 122694772,16,0,620,1,
96121189,3824,16,0,621, 12270459,4773,16,0,620,
96131,1443,3825,16,0, 122711,406,4774,16,0,
9614621,1,1695,3826,16, 12272620,1,41,4775,16,
96150,621,1,2198,3827, 122730,620,1,151,4776,
961616,0,621,1,447, 1227416,0,620,1,43,
96173828,16,0,621,1, 122754777,16,0,620,1,
96182458,876,1,2459,882, 122761585,4778,16,0,620,
96191,1958,3829,16,0, 122771,1990,4779,16,0,
9620621,1,2462,889,1, 12278620,1,2337,4780,16,
96211657,894,1,2464,899, 122790,620,1,509,4781,
96221,199,3830,16,0, 1228016,0,620,1,52,
9623621,1,459,3831,16, 122814782,16,0,620,1,
96240,621,1,462,3832, 12282381,4783,16,0,620,
962516,0,621,1,217, 122831,447,4784,16,0,
96263833,16,0,621,1, 12284620,1,166,4785,16,
96272227,908,1,1225,3834, 122850,620,1,462,4786,
962816,0,621,1,1479, 1228616,0,620,1,277,
96293835,16,0,621,1, 122874787,16,0,620,1,
96301731,3836,16,0,621, 122881695,4788,16,0,620,
96311,1989,916,1,1990, 122891,62,4789,16,0,
96323837,16,0,621,1, 12290693,1,1153,4790,16,
9633236,3838,16,0,621, 122910,620,1,2106,4791,
96341,1756,3839,16,0, 1229216,0,620,1,1335,
9635621,1,95,3840,19, 122934792,16,0,620,1,
9636620,1,95,3841,5, 1229471,4793,16,0,620,
963795,1,256,3842,16, 122951,182,4794,16,0,
96380,618,1,1261,3843, 12296620,1,76,4795,16,
963916,0,618,1,509, 122970,620,1,79,4796,
96403844,16,0,618,1, 1229816,0,620,1,1933,
96411515,3845,16,0,618, 122994797,16,0,620,1,
96421,2021,718,1,1775, 12300299,4798,16,0,620,
96433846,16,0,618,1, 123011,85,4799,16,0,
96442029,725,1,2030,731, 12302620,1,1515,4800,16,
96451,2031,736,1,2032, 123030,620,1,2198,4801,
9646741,1,2033,746,1, 1230416,0,620,1,89,
9647277,3847,16,0,618, 123054802,16,0,620,1,
96481,2035,752,1,2037, 123061834,4803,16,0,620,
9649757,1,2039,762,1, 123071,1622,4804,16,0,
965032,3848,16,0,618, 12308620,1,2413,4805,16,
96511,2041,768,1,2293, 123090,620,1,2075,4806,
96523849,16,0,618,1, 1231016,0,620,1,1731,
96532043,774,1,2045,779, 123114807,16,0,620,1,
96541,41,3850,16,0, 1231297,4808,16,0,620,
9655618,1,1297,3851,16, 123131,1297,4809,16,0,
96560,618,1,43,3852, 12314620,1,1189,4810,16,
965716,0,618,1,1803, 123150,620,1,102,4811,
9658787,1,1804,3853,16, 1231616,0,620,1,1261,
96590,618,1,299,3854, 123174812,16,0,620,1,
966016,0,618,1,52, 12318322,4813,16,0,620,
96613855,16,0,618,1, 123191,1958,4814,16,0,
96622318,3856,16,0,618, 12320620,1,199,4815,16,
96631,62,3857,16,0, 123210,620,1,1371,4816,
9664618,1,2075,3858,16, 1232216,0,620,1,217,
96650,618,1,1574,799, 123234817,16,0,620,1,
96661,71,3859,16,0, 12324152,4818,19,4819,4,
9667618,1,76,3860,16, 1232528,86,0,101,0,
96680,618,1,1834,3861, 1232699,0,116,0,111,
966916,0,618,1,2337, 123270,114,0,67,0,
96703862,16,0,618,1,
967179,3863,16,0,618,
96721,1335,3864,16,0,
9673618,1,322,3865,16,
96740,618,1,85,3866,
967516,0,618,1,89,
96763867,16,0,618,1,
9677346,3868,16,0,618,
96781,2105,814,1,2106,
96793869,16,0,618,1,
968097,3870,16,0,618,
96811,1860,821,1,2364,
9682827,1,102,3871,16,
96830,618,1,112,3872,
968416,0,618,1,1117,
96853873,16,0,618,1,
96861873,835,1,1876,3874,
968716,0,618,1,124,
96883875,16,0,618,1,
96892136,842,1,381,3876,
969016,0,618,1,525,
96913877,16,0,618,1,
9692137,3878,16,0,618,
96931,1901,3879,16,0,
9694618,1,2658,3880,16,
96950,618,1,1153,3881,
969616,0,618,1,151,
96973882,16,0,618,1,
96981407,3883,16,0,618,
96991,1659,3884,16,0,
9700618,1,2413,3885,16,
97010,618,1,406,3886,
970216,0,618,1,1371,
97033887,16,0,618,1,
9704166,3888,16,0,618,
97051,1622,3889,16,0,
9706618,1,1931,861,1,
97071933,3890,16,0,618,
97081,431,3891,16,0,
9709618,1,1585,3892,16,
97100,618,1,182,3893,
971116,0,618,1,1189,
97123894,16,0,618,1,
97131443,3895,16,0,618,
97141,1695,3896,16,0,
9715618,1,2198,3897,16,
97160,618,1,447,3898,
971716,0,618,1,2458,
9718876,1,2459,882,1,
97191958,3899,16,0,618,
97201,2462,889,1,1657,
9721894,1,2464,899,1,
9722199,3900,16,0,618,
97231,459,3901,16,0,
9724618,1,462,3902,16,
97250,618,1,217,3903,
972616,0,618,1,2227,
9727908,1,1225,3904,16,
97280,618,1,1479,3905,
972916,0,618,1,1731,
97303906,16,0,618,1,
97311989,916,1,1990,3907,
973216,0,618,1,236,
97333908,16,0,618,1,
97341756,3909,16,0,618,
97351,96,3910,19,103,
97361,96,3911,5,1,
97371,0,3912,16,0,
9738104,1,97,3913,19,
9739611,1,97,3914,5,
97401,1,0,3915,16,
97410,609,1,98,3916,
974219,636,1,98,3917,
97435,2,1,0,3918,
974416,0,638,1,2695,
97453919,16,0,634,1,
974699,3920,19,633,1,
974799,3921,5,2,1,
97480,3922,16,0,637,
97491,2695,3923,16,0,
9750631,1,100,3924,19,
9751296,1,100,3925,5,
97522,1,0,3926,16,
97530,557,1,2695,3927,
975416,0,294,1,101,
97553928,19,561,1,101,
97563929,5,4,1,0,
97573930,16,0,641,1,
97582695,3931,16,0,641,
97591,2706,3932,16,0,
9760559,1,2636,3933,16,
97610,559,1,102,3934,
976219,591,1,102,3935,
97635,2,1,2470,3936,
976416,0,664,1,2561,
97653937,16,0,589,1,
9766103,3938,19,463,1,
9767103,3939,5,4,1,
97682597,3940,16,0,558,
97691,2521,3941,16,0,
9770558,1,2470,3942,16,
97710,461,1,2561,3943,
977216,0,461,1,104,
97733944,19,141,1,104,
97743945,5,3,1,2642,
97753946,16,0,569,1,
97762506,3947,16,0,317,
97771,10,3948,16,0,
9778139,1,105,3949,19,
9779151,1,105,3950,5,
978017,1,0,3951,16,
97810,254,1,2075,3952,
978216,0,648,1,2337,
97833953,16,0,648,1,
97842413,3954,16,0,648,
97851,10,3955,16,0,
9786336,1,2198,3956,16,
97870,648,1,1901,3957,
978816,0,648,1,2642,
97893958,16,0,336,1,
979021,3959,16,0,149,
97911,2106,3960,16,0,
9792648,1,2506,3961,16,
97930,336,1,1804,3962,
979416,0,648,1,1990,
97953963,16,0,648,1,
97962695,3964,16,0,254,
97971,32,3965,16,0,
9798648,1,1958,3966,16,
97990,648,1,1775,3967,
980016,0,648,1,106,
98013968,19,130,1,106,
98023969,5,18,1,0,
98033970,16,0,128,1,
98042642,3971,16,0,137,
98051,2075,3972,16,0,
9806137,1,2337,3973,16,
98070,137,1,2413,3974,
980816,0,137,1,10,
98093975,16,0,137,1,
98102198,3976,16,0,137,
98111,1901,3977,16,0,
9812137,1,52,3978,16,
98130,193,1,21,3979,
981416,0,137,1,2106,
98153980,16,0,137,1,
98162506,3981,16,0,137,
98171,1804,3982,16,0,
9818137,1,1990,3983,16,
98190,137,1,2695,3984,
982016,0,128,1,32,
98213985,16,0,137,1,
98221958,3986,16,0,137,
98231,1775,3987,16,0,
9824137,1,107,3988,19,
9825658,1,107,3989,5,
98264,1,2597,3990,16,
98270,656,1,2521,3991,
982816,0,656,1,2470,
98293992,16,0,656,1,
98302561,3993,16,0,656,
98311,108,3994,19,335,
98321,108,3995,5,14,
98331,2517,3996,16,0,
9834437,1,2075,3997,16,
98350,506,1,2337,3998,
983616,0,506,1,2413,
98373999,16,0,506,1,
98381901,4000,16,0,506,
98391,2198,4001,16,0,
9840506,1,2106,4002,16,
98410,506,1,2653,4003,
984216,0,571,1,1804,
98434004,16,0,506,1,
98441990,4005,16,0,506,
98451,31,4006,16,0,
9846333,1,32,4007,16,
98470,506,1,1958,4008,
984816,0,506,1,1775,
98494009,16,0,506,1,
9850109,4010,19,302,1,
9851109,4011,5,1,1,
985232,4012,16,0,300,
98531,110,4013,19,261,
98541,110,4014,5,11,
98551,2075,4015,16,0,
9856577,1,2337,4016,16,
98570,265,1,2413,4017,
985816,0,445,1,1901,
98594018,16,0,391,1,
98602198,4019,16,0,319,
98611,2106,4020,16,0,
9862607,1,1804,4021,16,
98630,284,1,1990,4022,
986416,0,494,1,32,
98654023,16,0,329,1,
98661958,4024,16,0,450,
98671,1775,4025,16,0,
9868259,1,111,4026,19,
9869583,1,111,4027,5,
987011,1,2075,4028,16,
98710,581,1,2337,4029,
987216,0,581,1,2413,
98734030,16,0,581,1,
98741901,4031,16,0,581,
98751,2198,4032,16,0,
9876581,1,2106,4033,16,
98770,581,1,1804,4034,
987816,0,581,1,1990,
98794035,16,0,581,1,
988032,4036,16,0,581,
98811,1958,4037,16,0,
9882581,1,1775,4038,16,
98830,581,1,112,4039,
988419,645,1,112,4040,
98855,11,1,2075,4041,
988616,0,643,1,2337,
98874042,16,0,643,1,
98882413,4043,16,0,643,
98891,1901,4044,16,0,
9890643,1,2198,4045,16,
98910,643,1,2106,4046,
989216,0,643,1,1804,
98934047,16,0,643,1,
98941990,4048,16,0,643,
98951,32,4049,16,0,
9896643,1,1958,4050,16,
98970,643,1,1775,4051,
989816,0,643,1,113,
98994052,19,161,1,113,
99004053,5,31,1,1901,
99014054,16,0,647,1,
99021479,4055,16,0,551,
99031,2075,4056,16,0,
9904647,1,1695,4057,16,
99050,189,1,1756,4058,
990616,0,188,1,2413,
99074059,16,0,647,1,
99082198,4060,16,0,647,
99091,1876,4061,16,0,
9910661,1,1659,4062,16,
99110,188,1,1443,4063,
991216,0,522,1,1117,
99134064,16,0,159,1,
99141990,4065,16,0,647,
99151,1189,4066,16,0,
9916240,1,1775,4067,16,
99170,647,1,32,4068,
991816,0,647,1,2106,
99194069,16,0,647,1,
99201515,4070,16,0,579,
99211,2337,4071,16,0,
9922647,1,52,4072,16,
99230,592,1,1804,4073,
992416,0,647,1,1261,
99254074,16,0,298,1,
99261153,4075,16,0,247,
99271,1225,4076,16,0,
9928274,1,1335,4077,16,
99290,443,1,1933,4078,
993016,0,553,1,1834,
99314079,16,0,312,1,
99321297,4080,16,0,323,
99331,1407,4081,16,0,
9934568,1,2318,4082,16,
99350,188,1,1958,4083,
993616,0,647,1,1371,
99374084,16,0,438,1,
9938114,4085,19,531,1,
9939114,4086,5,11,1,
99402075,4087,16,0,529,
99411,2337,4088,16,0,
9942529,1,2413,4089,16,
99430,529,1,1901,4090,
994416,0,529,1,2198,
99454091,16,0,529,1,
99462106,4092,16,0,529,
99471,1804,4093,16,0,
9948529,1,1990,4094,16,
99490,529,1,32,4095,
995016,0,529,1,1958,
99514096,16,0,529,1,
99521775,4097,16,0,529,
99531,115,4098,19,527,
99541,115,4099,5,11,
99551,2075,4100,16,0,
9956525,1,2337,4101,16,
99570,525,1,2413,4102,
995816,0,525,1,1901,
99594103,16,0,525,1,
99602198,4104,16,0,525,
99611,2106,4105,16,0,
9962525,1,1804,4106,16,
99630,525,1,1990,4107,
996416,0,525,1,32,
99654108,16,0,525,1,
99661958,4109,16,0,525,
99671,1775,4110,16,0,
9968525,1,116,4111,19,
9969575,1,116,4112,5,
997011,1,2075,4113,16,
99710,573,1,2337,4114,
997216,0,573,1,2413,
99734115,16,0,573,1,
99741901,4116,16,0,573,
99751,2198,4117,16,0,
9976573,1,2106,4118,16,
99770,573,1,1804,4119,
997816,0,573,1,1990,
99794120,16,0,573,1,
998032,4121,16,0,573,
99811,1958,4122,16,0,
9982573,1,1775,4123,16,
99830,573,1,117,4124,
998419,521,1,117,4125,
99855,11,1,2075,4126,
998616,0,519,1,2337,
99874127,16,0,519,1,
99882413,4128,16,0,519,
99891,1901,4129,16,0,
9990519,1,2198,4130,16,
99910,519,1,2106,4131,
999216,0,519,1,1804,
99934132,16,0,519,1,
99941990,4133,16,0,519,
99951,32,4134,16,0,
9996519,1,1958,4135,16,
99970,519,1,1775,4136,
999816,0,519,1,118,
99994137,19,518,1,118,
100004138,5,11,1,2075,
100014139,16,0,516,1,
100022337,4140,16,0,516,
100031,2413,4141,16,0,
10004516,1,1901,4142,16,
100050,516,1,2198,4143,
1000616,0,516,1,2106,
100074144,16,0,516,1,
100081804,4145,16,0,516,
100091,1990,4146,16,0,
10010516,1,32,4147,16,
100110,516,1,1958,4148,
1001216,0,516,1,1775,
100134149,16,0,516,1,
10014119,4150,19,515,1,
10015119,4151,5,11,1,
100162075,4152,16,0,513,
100171,2337,4153,16,0,
10018513,1,2413,4154,16,
100190,513,1,1901,4155,
1002016,0,513,1,2198,
100214156,16,0,513,1,
100222106,4157,16,0,513,
100231,1804,4158,16,0,
10024513,1,1990,4159,16,
100250,513,1,32,4160,
1002616,0,513,1,1958,
100274161,16,0,513,1,
100281775,4162,16,0,513,
100291,120,4163,19,512,
100301,120,4164,5,11,
100311,2075,4165,16,0,
10032510,1,2337,4166,16,
100330,510,1,2413,4167,
1003416,0,510,1,1901,
100354168,16,0,510,1,
100362198,4169,16,0,510,
100371,2106,4170,16,0,
10038510,1,1804,4171,16,
100390,510,1,1990,4172,
1004016,0,510,1,32,
100414173,16,0,510,1,
100421958,4174,16,0,510,
100431,1775,4175,16,0,
10044510,1,121,4176,19,
10045509,1,121,4177,5,
1004611,1,2075,4178,16,
100470,507,1,2337,4179,
1004816,0,507,1,2413,
100494180,16,0,507,1,
100501901,4181,16,0,507,
100511,2198,4182,16,0,
10052507,1,2106,4183,16,
100530,507,1,1804,4184,
1005416,0,507,1,1990,
100554185,16,0,507,1,
1005632,4186,16,0,507,
100571,1958,4187,16,0,
10058507,1,1775,4188,16,
100590,507,1,122,4189,
1006019,147,1,122,4190,
100615,3,1,1756,4191,
1006216,0,283,1,2318,
100634192,16,0,297,1,
100641659,4193,16,0,145,
100651,123,4194,19,548,
100661,123,4195,5,68,
100671,1901,4196,16,0,
10068546,1,1479,4197,16,
100690,546,1,112,4198,
1007016,0,546,1,2293,
100714199,16,0,546,1,
100721804,4200,16,0,546,
100731,431,4201,16,0,
10074546,1,1443,4202,16,
100750,546,1,1756,4203,
1007616,0,546,1,124,
100774204,16,0,546,1,
10078525,4205,16,0,546,
100791,236,4206,16,0,
10080546,1,346,4207,16,
100810,546,1,1876,4208,
1008216,0,546,1,1659,
100834209,16,0,546,1,
100841225,4210,16,0,546,
100851,1117,4211,16,0,
10086546,1,137,4212,16,
100870,546,1,2318,4213,
1008816,0,546,1,1775,
100894214,16,0,546,1,
1009032,4215,16,0,546,
100911,1407,4216,16,0,
10092546,1,256,4217,16,
100930,546,1,459,4218,
1009416,0,546,1,406,
100954219,16,0,546,1,
1009641,4220,16,0,546,
100971,2658,4221,16,0,
10098546,1,43,4222,16,
100990,546,1,1585,4223,
1010016,0,546,1,1990,
101014224,16,0,546,1,
101022337,4225,16,0,546,
101031,509,4226,16,0,
10104546,1,52,4227,16,
101050,546,1,151,4228,
1010616,0,546,1,447,
101074229,16,0,546,1,
10108166,4230,16,0,546,
101091,462,4231,16,0,
10110546,1,277,4232,16,
101110,546,1,1695,4233,
1011216,0,546,1,62,
101134234,16,0,586,1,
101141153,4235,16,0,546,
101151,381,4236,16,0,
10116546,1,2106,4237,16,
101170,546,1,1335,4238,
1011816,0,546,1,71,
101194239,16,0,546,1,
10120182,4240,16,0,546,
101211,76,4241,16,0,
10122546,1,79,4242,16,
101230,546,1,1933,4243,
1012416,0,546,1,299,
101254244,16,0,546,1,
1012685,4245,16,0,546,
101271,1515,4246,16,0,
10128546,1,2198,4247,16,
101290,546,1,89,4248,
1013016,0,546,1,1834,
101314249,16,0,546,1,
101321622,4250,16,0,546,
101331,2413,4251,16,0,
10134546,1,2075,4252,16,
101350,546,1,1731,4253,
1013616,0,546,1,97,
101374254,16,0,546,1,
101381297,4255,16,0,546,
101391,1189,4256,16,0,
10140546,1,102,4257,16,
101410,546,1,1261,4258,
1014216,0,546,1,322,
101434259,16,0,546,1,
101441958,4260,16,0,546,
101451,199,4261,16,0,
10146546,1,1371,4262,16,
101470,546,1,217,4263,
1014816,0,546,1,124,
101494264,19,602,1,124,
101504265,5,2,1,459,
101514266,16,0,600,1,
1015241,4267,16,0,665,
101531,125,4268,19,606,
101541,125,4269,5,3,
101551,462,4270,16,0,
10156604,1,459,4271,16,
101570,630,1,41,4272,
1015816,0,630,1,126,
101594273,19,4274,4,36,
1016069,0,120,0,112,
101610,114,0,101,0,
10162115,0,115,0,105,
101630,111,0,110,0,
1016465,0,114,0,103,
101650,117,0,109,0,
10166101,0,110,0,116,
101670,1,126,4269,1,
10168127,4275,19,544,1,
10169127,4276,5,68,1,
101701901,4277,16,0,542,
101711,1479,4278,16,0,
10172542,1,112,4279,16,
101730,542,1,2293,4280,
1017416,0,542,1,1804,
101754281,16,0,542,1,
10176431,4282,16,0,542,
101771,1443,4283,16,0,
10178542,1,1756,4284,16,
101790,542,1,124,4285,
1018016,0,542,1,525,
101814286,16,0,542,1,
10182236,4287,16,0,542,
101831,346,4288,16,0,
10184542,1,1876,4289,16,
101850,542,1,1659,4290,
1018616,0,542,1,1225,
101874291,16,0,542,1,
101881117,4292,16,0,542,
101891,137,4293,16,0,
10190542,1,2318,4294,16,
101910,542,1,1775,4295,
1019216,0,542,1,32,
101934296,16,0,542,1,
101941407,4297,16,0,542,
101951,256,4298,16,0,
10196542,1,459,4299,16,
101970,542,1,406,4300,
1019816,0,542,1,41,
101994301,16,0,542,1,
102002658,4302,16,0,542,
102011,43,4303,16,0,
10202542,1,1585,4304,16,
102030,542,1,1990,4305,
1020416,0,542,1,2337,
102054306,16,0,542,1,
10206509,4307,16,0,542,
102071,52,4308,16,0,
10208542,1,151,4309,16,
102090,542,1,447,4310,
1021016,0,542,1,166,
102114311,16,0,542,1,
10212462,4312,16,0,542,
102131,277,4313,16,0,
10214542,1,1695,4314,16,
102150,542,1,62,4315,
1021616,0,587,1,1153,
102174316,16,0,542,1,
10218381,4317,16,0,542,
102191,2106,4318,16,0,
10220542,1,1335,4319,16,
102210,542,1,71,4320,
1022216,0,542,1,182,
102234321,16,0,542,1,
1022476,4322,16,0,542,
102251,79,4323,16,0,
10226542,1,1933,4324,16,
102270,542,1,299,4325,
1022816,0,542,1,85,
102294326,16,0,542,1,
102301515,4327,16,0,542,
102311,2198,4328,16,0,
10232542,1,89,4329,16,
102330,542,1,1834,4330,
1023416,0,542,1,1622,
102354331,16,0,542,1,
102362413,4332,16,0,542,
102371,2075,4333,16,0,
10238542,1,1731,4334,16,
102390,542,1,97,4335,
1024016,0,542,1,1297,
102414336,16,0,542,1,
102421189,4337,16,0,542,
102431,102,4338,16,0,
10244542,1,1261,4339,16,
102450,542,1,322,4340,
1024616,0,542,1,1958,
102474341,16,0,542,1,
10248199,4342,16,0,542,
102491,1371,4343,16,0,
10250542,1,217,4344,16,
102510,542,1,128,4345,
1025219,4346,4,28,86,
102530,101,0,99,0,
10254116,0,111,0,114,
102550,67,0,111,0,
10256110,0,115,0,116,
102570,97,0,110,0,
10258116,0,1,128,4276,
102591,129,4347,19,4348,
102604,32,82,0,111,
102610,116,0,97,0,
10262116,0,105,0,111,
102630,110,0,67,0,
10264111,0,110,0,115, 12328111,0,110,0,115,
102650,116,0,97,0, 123290,116,0,97,0,
10266110,0,116,0,1, 12330110,0,116,0,1,
10267129,4276,1,130,4349, 12331152,4749,1,153,4820,
1026819,4350,4,24,76, 1233219,4821,4,32,82,
102690,105,0,115,0, 123330,111,0,116,0,
10270116,0,67,0,111, 1233497,0,116,0,105,
102710,110,0,115,0, 123350,111,0,110,0,
10272116,0,97,0,110,
102730,116,0,1,130,
102744276,1,131,4351,19,
10275169,1,131,4352,5,
1027667,1,1901,4353,16,
102770,585,1,1479,4354,
1027816,0,533,1,112,
102794355,16,0,249,1,
102802293,4356,16,0,273,
102811,1804,4357,16,0,
10282585,1,431,4358,16,
102830,580,1,1443,4359,
1028416,0,468,1,1756,
102854360,16,0,673,1,
10286124,4361,16,0,258,
102871,525,4362,16,0,
10288305,1,236,4363,16,
102890,341,1,346,4364,
1029016,0,496,1,1876,
102914365,16,0,318,1,
102921659,4366,16,0,673,
102931,1225,4367,16,0,
10294248,1,1117,4368,16,
102950,219,1,137,4369,
1029616,0,272,1,2318,
102974370,16,0,673,1,
102981775,4371,16,0,585,
102991,32,4372,16,0,
10300585,1,1407,4373,16,
103010,487,1,256,4374,
1030216,0,395,1,459,
103034375,16,0,167,1,
10304406,4376,16,0,562,
103051,41,4377,16,0,
10306167,1,2658,4378,16,
103070,659,1,43,4379,
1030816,0,640,1,1990,
103094380,16,0,585,1,
103102337,4381,16,0,585,
103111,509,4382,16,0,
10312655,1,52,4383,16,
103130,594,1,151,4384,
1031416,0,282,1,447,
103154385,16,0,305,1,
10316166,4386,16,0,293,
103171,462,4387,16,0,
10318167,1,277,4388,16,
103190,434,1,1695,4389,
1032016,0,270,1,1261,
103214390,16,0,281,1,
103221153,4391,16,0,174,
103231,381,4392,16,0,
10324550,1,2106,4393,16,
103250,585,1,1335,4394,
1032616,0,326,1,71,
103274395,16,0,203,1,
10328182,4396,16,0,305,
103291,76,4397,16,0,
10330549,1,79,4398,16,
103310,218,1,1933,4399,
1033216,0,407,1,299,
103334400,16,0,444,1,
1033485,4401,16,0,457,
103351,1515,4402,16,0,
10336556,1,2198,4403,16,
103370,585,1,89,4404,
1033816,0,227,1,1834,
103394405,16,0,292,1,
103401622,4406,16,0,654,
103411,2413,4407,16,0,
10342585,1,2075,4408,16,
103430,585,1,1731,4409,
1034416,0,250,1,97,
103454410,16,0,411,1,
103461297,4411,16,0,328,
103471,1189,4412,16,0,
10348217,1,102,4413,16,
103490,238,1,1585,4414,
1035016,0,663,1,322,
103514415,16,0,458,1,
103521958,4416,16,0,585,
103531,199,4417,16,0,
10354316,1,1371,4418,16,
103550,396,1,217,4419,
1035616,0,325,1,132,
103574420,19,4421,4,36,
1035867,0,111,0,110, 1233667,0,111,0,110,
103590,115,0,116,0, 123370,115,0,116,0,
1036097,0,110,0,116, 1233897,0,110,0,116,
103610,69,0,120,0, 123390,1,153,4749,1,
10362112,0,114,0,101, 12340154,4822,19,4823,4,
103630,115,0,115,0, 1234124,76,0,105,0,
10364105,0,111,0,110, 12342115,0,116,0,67,
103650,1,132,4352,1, 123430,111,0,110,0,
10366133,4422,19,4423,4, 12344115,0,116,0,97,
1036730,73,0,100,0, 123450,110,0,116,0,
10368101,0,110,0,116, 123461,154,4749,1,155,
103690,69,0,120,0, 123474824,19,188,1,155,
10370112,0,114,0,101, 123484825,5,67,1,1901,
103710,115,0,115,0, 123494826,16,0,690,1,
10372105,0,111,0,110, 123501479,4827,16,0,611,
103730,1,133,4352,1, 123511,112,4828,16,0,
10374134,4424,19,4425,4, 12352276,1,2293,4829,16,
1037536,73,0,100,0, 123530,302,1,1804,4830,
10376101,0,110,0,116, 1235416,0,690,1,431,
103770,68,0,111,0, 123554831,16,0,685,1,
10378116,0,69,0,120, 123561443,4832,16,0,538,
103790,112,0,114,0, 123571,1756,4833,16,0,
10380101,0,115,0,115, 12358793,1,124,4834,16,
103810,105,0,111,0, 123590,283,1,525,4835,
10382110,0,1,134,4352, 1236016,0,340,1,236,
103831,135,4426,19,4427, 123614836,16,0,377,1,
103844,44,70,0,117, 12362346,4837,16,0,574,
103850,110,0,99,0, 123631,1876,4838,16,0,
10386116,0,105,0,111, 12364353,1,1659,4839,16,
103870,110,0,67,0, 123650,793,1,1225,4840,
1038897,0,108,0,108, 1236616,0,275,1,1117,
103890,69,0,120,0, 123674841,16,0,245,1,
10390112,0,114,0,101, 12368137,4842,16,0,301,
103910,115,0,115,0, 123691,2318,4843,16,0,
10392105,0,111,0,110, 12370793,1,1775,4844,16,
103930,1,135,4352,1, 123710,690,1,32,4845,
10394136,4428,19,4429,4, 1237216,0,690,1,1407,
1039532,66,0,105,0, 123734846,16,0,561,1,
10396110,0,97,0,114, 123742782,4847,16,0,256,
103970,121,0,69,0, 123751,256,4848,16,0,
12376431,1,459,4849,16,
123770,186,1,406,4850,
1237816,0,649,1,41,
123794851,16,0,186,1,
12380151,4852,16,0,315,
123811,43,4853,16,0,
12382738,1,1990,4854,16,
123830,690,1,2337,4855,
1238416,0,690,1,509,
123854856,16,0,762,1,
1238652,4857,16,0,702,
123871,381,4858,16,0,
12388629,1,447,4859,16,
123890,340,1,166,4860,
1239016,0,329,1,462,
123914861,16,0,186,1,
12392277,4862,16,0,476,
123931,1695,4863,16,0,
12394298,1,1261,4864,16,
123950,313,1,1153,4865,
1239616,0,193,1,2106,
123974866,16,0,690,1,
123981335,4867,16,0,362,
123991,71,4868,16,0,
12400229,1,182,4869,16,
124010,340,1,76,4870,
1240216,0,627,1,79,
124034871,16,0,244,1,
124041933,4872,16,0,443,
124051,299,4873,16,0,
12406503,1,85,4874,16,
124070,526,1,1515,4875,
1240816,0,644,1,2198,
124094876,16,0,690,1,
1241089,4877,16,0,257,
124111,1834,4878,16,0,
12412325,1,1622,4879,16,
124130,761,1,2413,4880,
1241416,0,690,1,2075,
124154881,16,0,690,1,
124161731,4882,16,0,277,
124171,97,4883,16,0,
12418447,1,1297,4884,16,
124190,364,1,1189,4885,
1242016,0,243,1,102,
124214886,16,0,265,1,
124221585,4887,16,0,773,
124231,322,4888,16,0,
12424530,1,1958,4889,16,
124250,690,1,199,4890,
1242616,0,351,1,1371,
124274891,16,0,432,1,
12428217,4892,16,0,361,
124291,156,4893,19,4894,
124304,36,67,0,111,
124310,110,0,115,0,
12432116,0,97,0,110,
124330,116,0,69,0,
10398120,0,112,0,114, 12434120,0,112,0,114,
103990,101,0,115,0, 124350,101,0,115,0,
10400115,0,105,0,111, 12436115,0,105,0,111,
104010,110,0,1,136, 124370,110,0,1,156,
104024352,1,137,4430,19, 124384825,1,157,4895,19,
104034431,4,30,85,0, 124394896,4,30,73,0,
10404110,0,97,0,114, 12440100,0,101,0,110,
104050,121,0,69,0, 124410,116,0,69,0,
10406120,0,112,0,114, 12442120,0,112,0,114,
104070,101,0,115,0, 124430,101,0,115,0,
10408115,0,105,0,111, 12444115,0,105,0,111,
104090,110,0,1,137, 124450,110,0,1,157,
104104352,1,138,4432,19, 124464825,1,158,4897,19,
104114433,4,36,84,0, 124474898,4,36,73,0,
10412121,0,112,0,101, 12448100,0,101,0,110,
104130,99,0,97,0, 124490,116,0,68,0,
10414115,0,116,0,69, 12450111,0,116,0,69,
104150,120,0,112,0, 124510,120,0,112,0,
10416114,0,101,0,115, 12452114,0,101,0,115,
104170,115,0,105,0, 124530,115,0,105,0,
10418111,0,110,0,1, 12454111,0,110,0,1,
10419138,4352,1,139,4434, 12455158,4825,1,159,4899,
1042019,4435,4,42,80, 1245619,4900,4,44,70,
104210,97,0,114,0, 124570,117,0,110,0,
10422101,0,110,0,116, 1245899,0,116,0,105,
104230,104,0,101,0, 124590,111,0,110,0,
10424115,0,105,0,115, 1246067,0,97,0,108,
124610,108,0,69,0,
12462120,0,112,0,114,
124630,101,0,115,0,
12464115,0,105,0,111,
124650,110,0,1,159,
124664825,1,160,4901,19,
124674902,4,32,66,0,
12468105,0,110,0,97,
124690,114,0,121,0,
1247069,0,120,0,112,
124710,114,0,101,0,
12472115,0,115,0,105,
124730,111,0,110,0,
124741,160,4825,1,161,
124754903,19,4904,4,30,
1247685,0,110,0,97,
124770,114,0,121,0,
1247869,0,120,0,112,
124790,114,0,101,0,
12480115,0,115,0,105,
124810,111,0,110,0,
124821,161,4825,1,162,
124834905,19,4906,4,36,
1248484,0,121,0,112,
124850,101,0,99,0,
1248697,0,115,0,116,
104250,69,0,120,0, 124870,69,0,120,0,
10426112,0,114,0,101, 12488112,0,114,0,101,
104270,115,0,115,0, 124890,115,0,115,0,
10428105,0,111,0,110, 12490105,0,111,0,110,
104290,1,139,4352,1, 124910,1,162,4825,1,
10430140,4436,19,4437,4, 12492163,4907,19,4908,4,
1043156,73,0,110,0, 1249342,80,0,97,0,
12494114,0,101,0,110,
124950,116,0,104,0,
12496101,0,115,0,105,
124970,115,0,69,0,
12498120,0,112,0,114,
124990,101,0,115,0,
12500115,0,105,0,111,
125010,110,0,1,163,
125024825,1,164,4909,19,
125034910,4,56,73,0,
12504110,0,99,0,114,
125050,101,0,109,0,
12506101,0,110,0,116,
125070,68,0,101,0,
1043299,0,114,0,101, 1250899,0,114,0,101,
104330,109,0,101,0, 125090,109,0,101,0,
10434110,0,116,0,68, 12510110,0,116,0,69,
104350,101,0,99,0, 125110,120,0,112,0,
10436114,0,101,0,109, 12512114,0,101,0,115,
104370,101,0,110,0, 125130,115,0,105,0,
10438116,0,69,0,120, 12514111,0,110,0,1,
104390,112,0,114,0, 12515164,4825,1,166,4911,
10440101,0,115,0,115, 1251619,822,1,166,4255,
104410,105,0,111,0, 125171,167,4912,19,832,
10442110,0,1,140,4352, 125181,167,4255,1,168,
104431,142,4438,19,683, 125194913,19,3549,1,168,
104441,142,3911,1,143, 125204258,1,169,4914,19,
104454439,19,705,1,143, 125213539,1,169,4258,1,
104463911,1,144,4440,19, 12522170,4915,19,3544,1,
104473192,1,144,3914,1, 12523170,4258,1,171,4916,
10448145,4441,19,3187,1, 1252419,3534,1,171,4258,
10449145,3914,1,146,4442, 125251,172,4917,19,3520,
1045019,3198,1,146,3914, 125261,172,4261,1,173,
104511,147,4443,19,3209, 125274918,19,3554,1,173,
104521,147,3914,1,148, 125284261,1,174,4919,19,
104534444,19,3220,1,148, 125293514,1,174,4265,1,
104543917,1,149,4445,19, 12530175,4920,19,3528,1,
104553226,1,149,3917,1, 12531175,4265,1,176,4921,
10456150,4446,19,3214,1, 1253219,805,1,176,4269,
10457150,3921,1,151,4447, 125331,177,4922,19,816,
1045819,3204,1,151,3921, 125341,177,4269,1,178,
104591,152,4448,19,689, 125354923,19,811,1,178,
104601,152,3925,1,153, 125364273,1,179,4924,19,
104614449,19,710,1,153, 12537827,1,179,4273,1,
104623925,1,154,4450,19, 12538180,4925,19,1835,1,
10463695,1,154,3929,1, 12539180,4279,1,181,4926,
10464155,4451,19,700,1, 1254019,1799,1,181,4279,
10465155,3929,1,156,4452, 125411,182,4927,19,1830,
1046619,1636,1,156,3935, 125421,182,4279,1,183,
104671,157,4453,19,1631, 125434928,19,1794,1,183,
104681,157,3935,1,158, 125444279,1,184,4929,19,
104694454,19,1622,1,158, 125451825,1,184,4279,1,
104703939,1,159,4455,19, 12546185,4930,19,1756,1,
104711680,1,159,3945,1, 12547185,4279,1,186,4931,
10472160,4456,19,1657,1, 1254819,1820,1,186,4279,
10473160,3945,1,161,4457, 125491,187,4932,19,1751,
1047419,1117,1,161,3950, 125501,187,4279,1,188,
104751,162,4458,19,902, 125514933,19,1815,1,188,
104761,162,3995,1,163, 125524279,1,189,4934,19,
104774459,19,886,1,163, 125531783,1,189,4279,1,
104783995,1,164,4460,19, 12554190,4935,19,1810,1,
10479892,1,164,4011,1, 12555190,4279,1,191,4936,
10480165,4461,19,880,1, 1255619,1778,1,191,4279,
10481165,4011,1,166,4462, 125571,192,4937,19,1805,
1048219,1145,1,166,4027, 125581,192,4279,1,193,
104831,167,4463,19,782, 125594938,19,1773,1,193,
104841,167,4014,1,168, 125604279,1,194,4939,19,
104854464,19,897,1,168, 125611878,1,194,4279,1,
104864014,1,169,4465,19, 12562195,4940,19,1768,1,
10487777,1,169,4014,1, 12563195,4279,1,196,4941,
10488170,4466,19,802,1, 1256419,1872,1,196,4283,
10489170,4014,1,171,4467, 125651,197,4942,19,1865,
1049019,771,1,171,4014, 125661,197,4289,1,198,
104911,172,4468,19,765, 125674943,19,1841,1,198,
104921,172,4014,1,173, 125684295,1,199,4944,19,
104934469,19,760,1,173, 125691859,1,199,4301,1,
104944014,1,174,4470,19, 12570200,4945,19,1853,1,
10495755,1,174,4014,1, 12571200,4307,1,201,4946,
10496175,4471,19,749,1, 1257219,1847,1,201,4313,
10497175,4014,1,176,4472, 125731,202,4947,19,1789,
1049819,744,1,176,4014, 125741,202,4319,1,203,
104991,177,4473,19,739, 125754948,19,1762,1,203,
105001,177,4014,1,178, 125764325,1,204,4949,19,
105014474,19,734,1,178, 125771941,1,204,4331,1,
105024014,1,179,4475,19, 12578205,4950,19,1907,1,
10503729,1,179,4014,1, 12579205,4331,1,206,4951,
10504180,4476,19,1152,1, 1258019,2302,1,206,4336,
10505180,4099,1,181,4477, 125811,207,4952,19,2294,
1050619,1290,1,181,4112, 125821,207,4339,1,208,
105071,182,4478,19,1139, 125834953,19,2327,1,208,
105081,182,4125,1,183, 125844342,1,209,4954,19,
105094479,19,1278,1,183, 125852285,1,209,4345,1,
105104125,1,184,4480,19, 12586210,4955,19,2279,1,
10511919,1,184,4138,1, 12587210,4348,1,211,4956,
10512185,4481,19,722,1, 1258819,2313,1,211,4351,
10513185,4138,1,186,4482, 125891,212,4957,19,1239,
1051419,817,1,186,4138, 125901,212,4354,1,213,
105151,187,4483,19,845, 125914958,19,1960,1,213,
105161,187,4138,1,188, 125924373,1,214,4959,19,
105174484,19,865,1,188, 125931886,1,214,4377,1,
105184151,1,189,4485,19, 12594215,4960,19,1899,1,
10519911,1,189,4151,1, 12595215,4384,1,216,4961,
10520190,4486,19,825,1, 1259619,1913,1,216,4389,
10521190,4164,1,191,4487, 125971,217,4962,19,1024,
1052219,838,1,191,4164, 125981,217,4461,1,218,
105231,192,4488,19,791, 125994963,19,1008,1,218,
105241,192,4177,1,193, 126004461,1,219,4964,19,
105254489,19,830,1,193, 126011014,1,219,4484,1,
105264177,1,194,4490,19, 12602220,4965,19,1002,1,
105271477,1,194,4190,1, 12603220,4484,1,221,4966,
10528195,4491,19,1158,1, 1260419,1267,1,221,4500,
10529195,4190,1,196,4492, 126051,222,4967,19,904,
1053019,1509,1,196,4190, 126061,222,4487,1,223,
105311,197,4493,19,1541, 126074968,19,1019,1,223,
105321,197,4190,1,198, 126084487,1,224,4969,19,
105334494,19,1406,1,198, 12609899,1,224,4487,1,
105344040,1,199,4495,19, 12610225,4970,19,924,1,
105351466,1,199,4040,1, 12611225,4487,1,226,4971,
10536200,4496,19,1133,1, 1261219,893,1,226,4487,
10537200,4053,1,201,4497, 126131,227,4972,19,887,
1053819,1573,1,201,4053, 126141,227,4487,1,228,
105391,202,4498,19,1504, 126154973,19,882,1,228,
105401,202,4053,1,203, 126164487,1,229,4974,19,
105414499,19,1451,1,203, 12617877,1,229,4487,1,
105424053,1,204,4500,19, 12618230,4975,19,871,1,
105431374,1,204,4053,1, 12619230,4487,1,231,4976,
10544205,4501,19,1300,1, 1262019,866,1,231,4487,
10545205,4053,1,206,4502, 126211,232,4977,19,861,
1054619,1310,1,206,4053, 126221,232,4487,1,233,
105471,207,4503,19,1128, 126234978,19,856,1,233,
105481,207,4053,1,208, 126244487,1,234,4979,19,
105494504,19,1557,1,208, 12625851,1,234,4487,1,
105504053,1,209,4505,19, 12626235,4980,19,1274,1,
105511499,1,209,4053,1, 12627235,4572,1,236,4981,
10552210,4506,19,1441,1, 1262819,1413,1,236,4585,
10553210,4053,1,211,4507, 126291,237,4982,19,1261,
1055419,1363,1,211,4053, 126301,237,4598,1,238,
105551,212,4508,19,1326, 126314983,19,1401,1,238,
105561,212,4053,1,213, 126324598,1,239,4984,19,
105574509,19,1111,1,213, 126331041,1,239,4611,1,
105584053,1,214,4510,19, 12634240,4985,19,844,1,
105591461,1,214,4053,1, 12635240,4611,1,241,4986,
10560215,4511,19,1487,1, 1263619,939,1,241,4611,
10561215,4053,1,216,4512, 126371,242,4987,19,968,
1056219,1434,1,216,4053, 126381,242,4611,1,243,
105631,217,4513,19,1456, 126394988,19,987,1,243,
105641,217,4053,1,218, 126404624,1,244,4989,19,
105654514,19,1266,1,218, 126411033,1,244,4624,1,
105664053,1,219,4515,19, 12642245,4990,19,947,1,
105671170,1,219,4053,1, 12643245,4637,1,246,4991,
10568220,4516,19,1100,1, 1264419,961,1,246,4637,
10569220,4053,1,221,4517, 126451,247,4992,19,913,
1057019,1531,1,221,4053, 126461,247,4650,1,248,
105711,222,4518,19,1482, 126474993,19,952,1,248,
105721,222,4053,1,223, 126484650,1,249,4994,19,
105734519,19,1429,1,223, 126491594,1,249,4663,1,
105744053,1,224,4520,19, 12650250,4995,19,1280,1,
105751295,1,224,4086,1, 12651250,4663,1,251,4996,
10576225,4521,19,1273,1, 1265219,1626,1,251,4663,
10577225,4086,1,226,4522, 126531,252,4997,19,1658,
1057819,1562,1,226,4276, 126541,252,4663,1,253,
105791,227,4523,19,1586, 126554998,19,1524,1,253,
105801,227,4276,1,228, 126564513,1,254,4999,19,
105814524,19,1552,1,228, 126571583,1,254,4513,1,
105824276,1,229,4525,19, 12658255,5000,19,1255,1,
105831547,1,229,4276,1, 12659255,4526,1,256,5001,
10584230,4526,19,1568,1, 1266019,1690,1,256,4526,
10585230,4276,1,231,4527, 126611,257,5002,19,1621,
1058619,1515,1,231,4276, 126621,257,4526,1,258,
105871,232,4528,19,1220, 126635003,19,1568,1,258,
105881,232,4276,1,233, 126644526,1,259,5004,19,
105894529,19,1395,1,233, 126651492,1,259,4526,1,
105904352,1,234,4530,19, 12666260,5005,19,1423,1,
105911181,1,234,4352,1, 12667260,4526,1,261,5006,
10592235,4531,19,1188,1, 1266819,1433,1,261,4526,
10593235,4352,1,236,4532, 126691,262,5007,19,1250,
1059419,1209,1,236,4352, 126701,262,4526,1,263,
105951,237,4533,19,1204, 126715008,19,1674,1,263,
105961,237,4352,1,238, 126724526,1,264,5009,19,
105974534,19,1199,1,238, 126731616,1,264,4526,1,
105984352,1,239,4535,19, 12674265,5010,19,1558,1,
105991194,1,239,4352,1, 12675265,4526,1,266,5011,
10600240,4536,19,1384,1, 1267619,1481,1,266,4526,
10601240,4352,1,241,4537, 126771,267,5012,19,1443,
1060219,1412,1,241,4352, 126781,267,4526,1,268,
106031,242,4538,19,1389, 126795013,19,1233,1,268,
106041,242,4352,1,243, 126804526,1,269,5014,19,
106054539,19,1379,1,243, 126811578,1,269,4526,1,
106064352,1,244,4540,19, 12682270,5015,19,1604,1,
106071369,1,244,4352,1, 12683270,4526,1,271,5016,
10608245,4541,19,1352,1, 1268419,1551,1,271,4526,
10609245,4352,1,246,4542, 126851,272,5017,19,1573,
1061019,1305,1,246,4352, 126861,272,4526,1,273,
106111,247,4543,19,1214, 126875018,19,1389,1,273,
106121,247,4352,1,248, 126884526,1,274,5019,19,
106134544,19,1175,1,248, 126891293,1,274,4526,1,
106144352,1,249,4545,19, 12690275,5020,19,1222,1,
106151123,1,249,4352,1, 12691275,4526,1,276,5021,
10616250,4546,19,1581,1, 1269219,1648,1,276,4526,
10617250,4352,1,251,4547, 126931,277,5022,19,1599,
1061819,1536,1,251,4352, 126941,277,4526,1,278,
106191,252,4548,19,1526, 126955023,19,1546,1,278,
106201,252,4352,1,253, 126964526,1,279,5024,19,
106214549,19,1521,1,253, 126971418,1,279,4559,1,
106224352,1,254,4550,19, 12698280,5025,19,1396,1,
106231472,1,254,4352,1, 12699280,4559,1,281,5026,
10624255,4551,19,1446,1, 1270019,1679,1,281,4749,
10625255,4352,1,256,4552, 127011,282,5027,19,1708,
1062619,1422,1,256,4352, 127021,282,4749,1,283,
106271,257,4553,19,1417, 127035028,19,1669,1,283,
106281,257,4352,1,258, 127044749,1,284,5029,19,
106294554,19,1358,1,258, 127051664,1,284,4749,1,
106304352,1,259,4555,19, 12706285,5030,19,1685,1,
106311334,1,259,4352,1, 12707285,4749,1,286,5031,
10632260,4556,19,1400,1, 1270819,1632,1,286,4749,
10633260,4352,1,261,4557, 127091,287,5032,19,1343,
1063419,1493,1,261,4352, 127101,287,4749,1,288,
106351,262,4558,19,1347, 127115033,19,1513,1,288,
106361,262,4352,1,263, 127124825,1,289,5034,19,
106374559,19,1341,1,263, 127131304,1,289,4825,1,
106384352,1,264,4560,19, 12714290,5035,19,1311,1,
106391321,1,264,4352,1, 12715290,4825,1,291,5036,
10640265,4561,19,1284,1, 1271619,1332,1,291,4825,
10641265,4352,1,266,4562, 127171,292,5037,19,1327,
1064219,1261,1,266,4352, 127181,292,4825,1,293,
106431,267,4563,19,1106, 127195038,19,1322,1,293,
106441,267,4352,1,268, 127204825,1,294,5039,19,
106454564,19,1596,1,268, 127211317,1,294,4825,1,
106464352,1,269,4565,19, 12722295,5040,19,1502,1,
106471226,1,269,4352,1, 12723295,4825,1,296,5041,
10648270,4566,19,1231,1, 1272419,1530,1,296,4825,
10649270,4352,1,271,4567, 127251,297,5042,19,1507,
1065019,1251,1,271,4352, 127261,297,4825,1,298,
106511,272,4568,19,1241, 127275043,19,1497,1,298,
106521,272,4352,1,273, 127284825,1,299,5044,19,
106534569,19,1246,1,273, 127291487,1,299,4825,1,
106544352,1,274,4570,19, 12730300,5045,19,1470,1,
106551236,1,274,4352,1, 12731300,4825,1,301,5046,
10656275,4571,19,1591,1, 1273219,1428,1,301,4825,
10657275,4352,1,276,4572, 127331,302,5047,19,1337,
1065819,1256,1,276,4352, 127341,302,4825,1,303,
106591,277,4573,19,1316, 127355048,19,1298,1,303,
106601,277,4195,1,278, 127364825,1,304,5049,19,
106614574,19,1650,1,278, 127371245,1,304,4825,1,
106624265,1,279,4575,19, 12738305,5050,19,1703,1,
106631686,1,279,4265,1, 12739305,4825,1,306,5051,
10664280,4576,19,1666,1, 1274019,1653,1,306,4825,
10665280,4269,1,281,4577, 127411,307,5052,19,1643,
1066619,1985,1,281,3969, 127421,307,4825,1,308,
106671,282,4578,19,1980, 127435053,19,1638,1,308,
106681,282,3969,1,283, 127444825,1,309,5054,19,
106694579,19,1975,1,283, 127451589,1,309,4825,1,
106703969,1,284,4580,19, 12746310,5055,19,1563,1,
106711970,1,284,3969,1, 12747310,4825,1,311,5056,
10672285,4581,19,1965,1, 1274819,1540,1,311,4825,
10673285,3969,1,286,4582, 127491,312,5057,19,1535,
1067419,1960,1,286,3969, 127501,312,4825,1,313,
106751,287,4583,19,1955, 127515058,19,1476,1,313,
106761,287,3969,1,288, 127524825,1,314,5059,19,
106774584,19,1944,1,288, 127531451,1,314,4825,1,
106783989,1,289,4585,19, 12754315,5060,19,1518,1,
106791939,1,289,3989,1, 12755315,4825,1,316,5061,
10680290,4586,19,1934,1, 1275619,1610,1,316,4825,
10681290,3989,1,291,4587, 127571,317,5062,19,1465,
1068219,1929,1,291,3989, 127581,317,4825,1,318,
106831,292,4588,19,1924, 127595063,19,1458,1,318,
106841,292,3989,1,293, 127604825,1,319,5064,19,
106854589,19,1919,1,293, 127611438,1,319,4825,1,
106863989,1,294,4590,19, 12762320,5065,19,1407,1,
106871914,1,294,3989,1, 12763320,4825,1,321,5066,
10688295,4591,19,1909,1, 1276419,1384,1,321,4825,
10689295,3989,1,296,4592, 127651,322,5067,19,1228,
1069019,1904,1,296,3989, 127661,322,4825,1,323,
106911,297,4593,19,1739, 127675068,19,1718,1,323,
106921,297,3989,1,298, 127684825,1,324,5069,19,
106934594,19,1898,1,298, 127691349,1,324,4825,1,
106943989,1,299,4595,19, 12770325,5070,19,1354,1,
106951893,1,299,3989,1, 12771325,4825,1,326,5071,
10696300,4596,19,1888,1, 1277219,1374,1,326,4825,
10697300,3989,1,301,4597, 127731,327,5072,19,1364,
1069819,1732,1,301,3989, 127741,327,4825,1,328,
106991,302,4598,19,1883, 127755073,19,1369,1,328,
107001,302,3989,1,303, 127764825,1,329,5074,19,
107014599,19,1878,1,303, 127771359,1,329,4825,1,
107023989,1,304,4600,19, 12778330,5075,19,1713,1,
107031873,1,304,3989,1, 12779330,4825,1,331,5076,
10704305,4601,19,1868,1, 1278019,1379,1,331,4825,
10705305,3989,1,306,4602, 127811,332,5077,19,1698,
1070619,1863,1,306,3989, 127821,332,4668,1,333,
107071,307,4603,19,1858, 127835078,19,1954,1,333,
107081,307,3989,1,308, 127844738,1,334,5079,19,
107094604,19,1725,1,308, 127851947,1,334,4738,1,
107103989,1,309,4605,19, 12786335,5080,19,1924,1,
107111852,1,309,3989,1, 12787335,4742,1,336,5081,
10712310,4606,19,1847,1, 1278819,2270,1,336,4393,
10713310,3989,1,311,4607, 127891,337,5082,19,2265,
1071419,1842,1,311,3989, 127901,337,4393,1,338,
107151,312,4608,19,1719, 127915083,19,2260,1,338,
107161,312,3989,1,313, 127924393,1,339,5084,19,
107174609,19,1836,1,313, 127932255,1,339,4393,1,
107183989,1,314,4610,19, 12794340,5085,19,2250,1,
107191767,1,314,3989,1, 12795340,4393,1,341,5086,
10720315,4611,19,1831,1, 1279619,2245,1,341,4393,
10721315,3989,1,316,4612, 127971,342,5087,19,2240,
1072219,1826,1,316,3989, 127981,342,4393,1,343,
107231,317,4613,19,1821, 127995088,19,2229,1,343,
107241,317,3989,1,318, 128004413,1,344,5089,19,
107254614,19,1816,1,318, 128012224,1,344,4413,1,
107263989,1,319,4615,19, 12802345,5090,19,2219,1,
107271811,1,319,3989,1, 12803345,4413,1,346,5091,
10728320,4616,19,1806,1, 1280419,2214,1,346,4413,
10729320,3989,1,321,4617, 128051,347,5092,19,2209,
1073019,1801,1,321,3989, 128061,347,4413,1,348,
107311,322,4618,19,4619, 128075093,19,2204,1,348,
128084413,1,349,5094,19,
128092199,1,349,4413,1,
12810350,5095,19,2194,1,
12811350,4413,1,351,5096,
1281219,2188,1,351,4419,
128131,352,5097,19,2014,
128141,352,4419,1,353,
128155098,19,2182,1,353,
128164419,1,354,5099,19,
128172177,1,354,4419,1,
12818355,5100,19,2172,1,
12819355,4419,1,356,5101,
1282019,2007,1,356,4419,
128211,357,5102,19,2167,
128221,357,4419,1,358,
128235103,19,2162,1,358,
128244419,1,359,5104,19,
128252157,1,359,4425,1,
12826360,5105,19,2152,1,
12827360,4425,1,361,5106,
1282819,2146,1,361,4431,
128291,362,5107,19,2141,
128301,362,4431,1,363,
128315108,19,1998,1,363,
128324431,1,364,5109,19,
128332135,1,364,4431,1,
12834365,5110,19,2130,1,
12835365,4431,1,366,5111,
1283619,2125,1,366,4431,
128371,367,5112,19,1992,
128381,367,4431,1,368,
128395113,19,2119,1,368,
128404431,1,369,5114,19,
128412047,1,369,4431,1,
12842370,5115,19,2114,1,
12843370,4431,1,371,5116,
1284419,2109,1,371,4437,
128451,372,5117,19,2104,
128461,372,4437,1,373,
128475118,19,2099,1,373,
128484437,1,374,5119,19,
128492093,1,374,4443,1,
12850375,5120,19,2087,1,
12851375,4449,1,376,5121,
1285219,2081,1,376,4455,
128531,377,5122,19,5123,
107324,50,65,0,114, 128544,50,65,0,114,
107330,103,0,117,0, 128550,103,0,117,0,
10734109,0,101,0,110, 12856109,0,101,0,110,
@@ -10739,16 +12861,16 @@ public yyLSLSyntax
107390,111,0,110,0, 128610,111,0,110,0,
1074076,0,105,0,115, 1286276,0,105,0,115,
107410,116,0,95,0, 128630,116,0,95,0,
1074251,0,1,322,3945, 1286451,0,1,377,4331,
107431,323,4620,19,4621, 128651,378,5124,19,5125,
107444,28,65,0,114, 128664,28,65,0,114,
107450,103,0,117,0, 128670,103,0,117,0,
10746109,0,101,0,110, 12868109,0,101,0,110,
107470,116,0,76,0, 128690,116,0,76,0,
10748105,0,115,0,116, 12870105,0,115,0,116,
107490,95,0,51,0, 128710,95,0,51,0,
107501,323,4265,1,324, 128721,378,4738,1,379,
107514622,19,4623,4,50, 128735126,19,5127,4,50,
1075265,0,114,0,103, 1287465,0,114,0,103,
107530,117,0,109,0, 128750,117,0,109,0,
10754101,0,110,0,116, 12876101,0,110,0,116,
@@ -10759,16 +12881,16 @@ public yyLSLSyntax
107590,110,0,76,0, 128810,110,0,76,0,
10760105,0,115,0,116, 12882105,0,115,0,116,
107610,95,0,52,0, 128830,95,0,52,0,
107621,324,3945,1,325, 128841,379,4331,1,380,
107634624,19,4625,4,28, 128855128,19,5129,4,28,
1076465,0,114,0,103, 1288665,0,114,0,103,
107650,117,0,109,0, 128870,117,0,109,0,
10766101,0,110,0,116, 12888101,0,110,0,116,
107670,76,0,105,0, 128890,76,0,105,0,
10768115,0,116,0,95, 12890115,0,116,0,95,
107690,52,0,1,325, 128910,52,0,1,380,
107704265,1,326,4626,19, 128924738,1,381,5130,19,
107714627,4,50,65,0, 128935131,4,50,65,0,
10772114,0,103,0,117, 12894114,0,103,0,117,
107730,109,0,101,0, 128950,109,0,101,0,
10774110,0,116,0,68, 12896110,0,116,0,68,
@@ -10778,13 +12900,18 @@ public yyLSLSyntax
10778105,0,111,0,110, 12900105,0,111,0,110,
107790,76,0,105,0, 129010,76,0,105,0,
10780115,0,116,0,95, 12902115,0,116,0,95,
107810,53,0,1,326, 129030,53,0,1,381,
107823945,2,0,0}; 129044331,2,0,0};
10783new Sfactory(this,"ExpressionArgument_1",new SCreator(ExpressionArgument_1_factory)); 12905new Sfactory(this,"ExpressionArgument_1",new SCreator(ExpressionArgument_1_factory));
10784new Sfactory(this,"SimpleAssignment_8",new SCreator(SimpleAssignment_8_factory)); 12906new Sfactory(this,"VectorArgStateEvent",new SCreator(VectorArgStateEvent_factory));
12907new Sfactory(this,"IntVecVecArgStateEvent",new SCreator(IntVecVecArgStateEvent_factory));
12908new Sfactory(this,"IntArgStateEvent_1",new SCreator(IntArgStateEvent_1_factory));
12909new Sfactory(this,"SimpleAssignment_9",new SCreator(SimpleAssignment_9_factory));
10785new Sfactory(this,"StatementList_1",new SCreator(StatementList_1_factory)); 12910new Sfactory(this,"StatementList_1",new SCreator(StatementList_1_factory));
12911new Sfactory(this,"RotDeclaration_1",new SCreator(RotDeclaration_1_factory));
12912new Sfactory(this,"IntRotRotArgEvent_1",new SCreator(IntRotRotArgEvent_1_factory));
10786new Sfactory(this,"StateChange_1",new SCreator(StateChange_1_factory)); 12913new Sfactory(this,"StateChange_1",new SCreator(StateChange_1_factory));
10787new Sfactory(this,"StateChange_2",new SCreator(StateChange_2_factory)); 12914new Sfactory(this,"EmptyStatement",new SCreator(EmptyStatement_factory));
10788new Sfactory(this,"Declaration",new SCreator(Declaration_factory)); 12915new Sfactory(this,"Declaration",new SCreator(Declaration_factory));
10789new Sfactory(this,"IdentExpression",new SCreator(IdentExpression_factory)); 12916new Sfactory(this,"IdentExpression",new SCreator(IdentExpression_factory));
10790new Sfactory(this,"error",new SCreator(error_factory)); 12917new Sfactory(this,"error",new SCreator(error_factory));
@@ -10797,20 +12924,25 @@ new Sfactory(this,"SimpleAssignment_19",new SCreator(SimpleAssignment_19_factory
10797new Sfactory(this,"BinaryExpression_9",new SCreator(BinaryExpression_9_factory)); 12924new Sfactory(this,"BinaryExpression_9",new SCreator(BinaryExpression_9_factory));
10798new Sfactory(this,"VectorConstant_1",new SCreator(VectorConstant_1_factory)); 12925new Sfactory(this,"VectorConstant_1",new SCreator(VectorConstant_1_factory));
10799new Sfactory(this,"ParenthesisExpression",new SCreator(ParenthesisExpression_factory)); 12926new Sfactory(this,"ParenthesisExpression",new SCreator(ParenthesisExpression_factory));
12927new Sfactory(this,"StatementList",new SCreator(StatementList_factory));
12928new Sfactory(this,"IntRotRotArgEvent",new SCreator(IntRotRotArgEvent_factory));
10800new Sfactory(this,"UnaryExpression",new SCreator(UnaryExpression_factory)); 12929new Sfactory(this,"UnaryExpression",new SCreator(UnaryExpression_factory));
10801new Sfactory(this,"IdentDotExpression_1",new SCreator(IdentDotExpression_1_factory)); 12930new Sfactory(this,"IdentDotExpression_1",new SCreator(IdentDotExpression_1_factory));
10802new Sfactory(this,"ArgumentList_4",new SCreator(ArgumentList_4_factory)); 12931new Sfactory(this,"ArgumentList_4",new SCreator(ArgumentList_4_factory));
10803new Sfactory(this,"Typename",new SCreator(Typename_factory)); 12932new Sfactory(this,"Typename",new SCreator(Typename_factory));
10804new Sfactory(this,"IfStatement_1",new SCreator(IfStatement_1_factory)); 12933new Sfactory(this,"IfStatement_1",new SCreator(IfStatement_1_factory));
12934new Sfactory(this,"RotationConstant_1",new SCreator(RotationConstant_1_factory));
10805new Sfactory(this,"Assignment",new SCreator(Assignment_factory)); 12935new Sfactory(this,"Assignment",new SCreator(Assignment_factory));
12936new Sfactory(this,"IfStatement_4",new SCreator(IfStatement_4_factory));
10806new Sfactory(this,"CompoundStatement_1",new SCreator(CompoundStatement_1_factory)); 12937new Sfactory(this,"CompoundStatement_1",new SCreator(CompoundStatement_1_factory));
10807new Sfactory(this,"CompoundStatement_2",new SCreator(CompoundStatement_2_factory)); 12938new Sfactory(this,"CompoundStatement_2",new SCreator(CompoundStatement_2_factory));
12939new Sfactory(this,"KeyIntIntArgumentDeclarationList_1",new SCreator(KeyIntIntArgumentDeclarationList_1_factory));
10808new Sfactory(this,"BinaryExpression_8",new SCreator(BinaryExpression_8_factory)); 12940new Sfactory(this,"BinaryExpression_8",new SCreator(BinaryExpression_8_factory));
12941new Sfactory(this,"VectorArgEvent",new SCreator(VectorArgEvent_factory));
10809new Sfactory(this,"ReturnStatement_1",new SCreator(ReturnStatement_1_factory)); 12942new Sfactory(this,"ReturnStatement_1",new SCreator(ReturnStatement_1_factory));
10810new Sfactory(this,"IdentDotExpression",new SCreator(IdentDotExpression_factory)); 12943new Sfactory(this,"IdentDotExpression",new SCreator(IdentDotExpression_factory));
10811new Sfactory(this,"Argument",new SCreator(Argument_factory)); 12944new Sfactory(this,"Argument",new SCreator(Argument_factory));
10812new Sfactory(this,"State_2",new SCreator(State_2_factory)); 12945new Sfactory(this,"State_2",new SCreator(State_2_factory));
10813new Sfactory(this,"WhileStatement_1",new SCreator(WhileStatement_1_factory));
10814new Sfactory(this,"GlobalDefinitions_3",new SCreator(GlobalDefinitions_3_factory)); 12946new Sfactory(this,"GlobalDefinitions_3",new SCreator(GlobalDefinitions_3_factory));
10815new Sfactory(this,"GlobalDefinitions_4",new SCreator(GlobalDefinitions_4_factory)); 12947new Sfactory(this,"GlobalDefinitions_4",new SCreator(GlobalDefinitions_4_factory));
10816new Sfactory(this,"Event_1",new SCreator(Event_1_factory)); 12948new Sfactory(this,"Event_1",new SCreator(Event_1_factory));
@@ -10820,9 +12952,9 @@ new Sfactory(this,"Event_4",new SCreator(Event_4_factory));
10820new Sfactory(this,"Event_5",new SCreator(Event_5_factory)); 12952new Sfactory(this,"Event_5",new SCreator(Event_5_factory));
10821new Sfactory(this,"SimpleAssignment_5",new SCreator(SimpleAssignment_5_factory)); 12953new Sfactory(this,"SimpleAssignment_5",new SCreator(SimpleAssignment_5_factory));
10822new Sfactory(this,"Typename_1",new SCreator(Typename_1_factory)); 12954new Sfactory(this,"Typename_1",new SCreator(Typename_1_factory));
10823new Sfactory(this,"Typename_2",new SCreator(Typename_2_factory)); 12955new Sfactory(this,"VoidArgStateEvent_1",new SCreator(VoidArgStateEvent_1_factory));
10824new Sfactory(this,"Typename_3",new SCreator(Typename_3_factory)); 12956new Sfactory(this,"Typename_3",new SCreator(Typename_3_factory));
10825new Sfactory(this,"Typename_4",new SCreator(Typename_4_factory)); 12957new Sfactory(this,"IntRotRotArgStateEvent",new SCreator(IntRotRotArgStateEvent_factory));
10826new Sfactory(this,"Typename_5",new SCreator(Typename_5_factory)); 12958new Sfactory(this,"Typename_5",new SCreator(Typename_5_factory));
10827new Sfactory(this,"Typename_6",new SCreator(Typename_6_factory)); 12959new Sfactory(this,"Typename_6",new SCreator(Typename_6_factory));
10828new Sfactory(this,"Typename_7",new SCreator(Typename_7_factory)); 12960new Sfactory(this,"Typename_7",new SCreator(Typename_7_factory));
@@ -10830,10 +12962,16 @@ new Sfactory(this,"ArgumentDeclarationList",new SCreator(ArgumentDeclarationList
10830new Sfactory(this,"ConstantExpression",new SCreator(ConstantExpression_factory)); 12962new Sfactory(this,"ConstantExpression",new SCreator(ConstantExpression_factory));
10831new Sfactory(this,"LSLProgramRoot_1",new SCreator(LSLProgramRoot_1_factory)); 12963new Sfactory(this,"LSLProgramRoot_1",new SCreator(LSLProgramRoot_1_factory));
10832new Sfactory(this,"LSLProgramRoot_2",new SCreator(LSLProgramRoot_2_factory)); 12964new Sfactory(this,"LSLProgramRoot_2",new SCreator(LSLProgramRoot_2_factory));
12965new Sfactory(this,"KeyIntIntArgEvent_1",new SCreator(KeyIntIntArgEvent_1_factory));
10833new Sfactory(this,"States_1",new SCreator(States_1_factory)); 12966new Sfactory(this,"States_1",new SCreator(States_1_factory));
10834new Sfactory(this,"States_2",new SCreator(States_2_factory)); 12967new Sfactory(this,"States_2",new SCreator(States_2_factory));
10835new Sfactory(this,"FunctionCallExpression_1",new SCreator(FunctionCallExpression_1_factory)); 12968new Sfactory(this,"FunctionCallExpression_1",new SCreator(FunctionCallExpression_1_factory));
12969new Sfactory(this,"KeyArgEvent_1",new SCreator(KeyArgEvent_1_factory));
10836new Sfactory(this,"ForLoopStatement",new SCreator(ForLoopStatement_factory)); 12970new Sfactory(this,"ForLoopStatement",new SCreator(ForLoopStatement_factory));
12971new Sfactory(this,"IntArgStateEvent",new SCreator(IntArgStateEvent_factory));
12972new Sfactory(this,"StateBody_15",new SCreator(StateBody_15_factory));
12973new Sfactory(this,"IntRotRotArgumentDeclarationList_1",new SCreator(IntRotRotArgumentDeclarationList_1_factory));
12974new Sfactory(this,"IntArgEvent_9",new SCreator(IntArgEvent_9_factory));
10837new Sfactory(this,"DoWhileStatement_1",new SCreator(DoWhileStatement_1_factory)); 12975new Sfactory(this,"DoWhileStatement_1",new SCreator(DoWhileStatement_1_factory));
10838new Sfactory(this,"DoWhileStatement_2",new SCreator(DoWhileStatement_2_factory)); 12976new Sfactory(this,"DoWhileStatement_2",new SCreator(DoWhileStatement_2_factory));
10839new Sfactory(this,"ForLoopStatement_4",new SCreator(ForLoopStatement_4_factory)); 12977new Sfactory(this,"ForLoopStatement_4",new SCreator(ForLoopStatement_4_factory));
@@ -10842,74 +12980,93 @@ new Sfactory(this,"SimpleAssignment_12",new SCreator(SimpleAssignment_12_factory
10842new Sfactory(this,"SimpleAssignment_13",new SCreator(SimpleAssignment_13_factory)); 12980new Sfactory(this,"SimpleAssignment_13",new SCreator(SimpleAssignment_13_factory));
10843new Sfactory(this,"JumpLabel",new SCreator(JumpLabel_factory)); 12981new Sfactory(this,"JumpLabel",new SCreator(JumpLabel_factory));
10844new Sfactory(this,"SimpleAssignment_15",new SCreator(SimpleAssignment_15_factory)); 12982new Sfactory(this,"SimpleAssignment_15",new SCreator(SimpleAssignment_15_factory));
10845new Sfactory(this,"SimpleAssignment_17",new SCreator(SimpleAssignment_17_factory)); 12983new Sfactory(this,"IntVecVecArgEvent",new SCreator(IntVecVecArgEvent_factory));
10846new Sfactory(this,"SimpleAssignment_18",new SCreator(SimpleAssignment_18_factory)); 12984new Sfactory(this,"VecDeclaration",new SCreator(VecDeclaration_factory));
10847new Sfactory(this,"JumpStatement_1",new SCreator(JumpStatement_1_factory)); 12985new Sfactory(this,"StateBody_14",new SCreator(StateBody_14_factory));
10848new Sfactory(this,"GlobalDefinitions",new SCreator(GlobalDefinitions_factory)); 12986new Sfactory(this,"GlobalDefinitions",new SCreator(GlobalDefinitions_factory));
12987new Sfactory(this,"StateBody_16",new SCreator(StateBody_16_factory));
12988new Sfactory(this,"KeyIntIntArgumentDeclarationList",new SCreator(KeyIntIntArgumentDeclarationList_factory));
12989new Sfactory(this,"ConstantExpression_1",new SCreator(ConstantExpression_1_factory));
12990new Sfactory(this,"VoidArgEvent_4",new SCreator(VoidArgEvent_4_factory));
10849new Sfactory(this,"FunctionCall_1",new SCreator(FunctionCall_1_factory)); 12991new Sfactory(this,"FunctionCall_1",new SCreator(FunctionCall_1_factory));
10850new Sfactory(this,"ArgumentList_3",new SCreator(ArgumentList_3_factory)); 12992new Sfactory(this,"Assignment_1",new SCreator(Assignment_1_factory));
10851new Sfactory(this,"Assignment_2",new SCreator(Assignment_2_factory)); 12993new Sfactory(this,"Assignment_2",new SCreator(Assignment_2_factory));
12994new Sfactory(this,"IntVecVecArgEvent_1",new SCreator(IntVecVecArgEvent_1_factory));
10852new Sfactory(this,"TypecastExpression_1",new SCreator(TypecastExpression_1_factory)); 12995new Sfactory(this,"TypecastExpression_1",new SCreator(TypecastExpression_1_factory));
10853new Sfactory(this,"SimpleAssignment_21",new SCreator(SimpleAssignment_21_factory)); 12996new Sfactory(this,"SimpleAssignment_21",new SCreator(SimpleAssignment_21_factory));
10854new Sfactory(this,"SimpleAssignment_22",new SCreator(SimpleAssignment_22_factory)); 12997new Sfactory(this,"SimpleAssignment_22",new SCreator(SimpleAssignment_22_factory));
10855new Sfactory(this,"SimpleAssignment_23",new SCreator(SimpleAssignment_23_factory)); 12998new Sfactory(this,"KeyIntIntArgStateEvent",new SCreator(KeyIntIntArgStateEvent_factory));
10856new Sfactory(this,"TypecastExpression_9",new SCreator(TypecastExpression_9_factory)); 12999new Sfactory(this,"TypecastExpression_9",new SCreator(TypecastExpression_9_factory));
13000new Sfactory(this,"VoidArgEvent_2",new SCreator(VoidArgEvent_2_factory));
13001new Sfactory(this,"VoidArgEvent_3",new SCreator(VoidArgEvent_3_factory));
10857new Sfactory(this,"ArgumentDeclarationList_1",new SCreator(ArgumentDeclarationList_1_factory)); 13002new Sfactory(this,"ArgumentDeclarationList_1",new SCreator(ArgumentDeclarationList_1_factory));
10858new Sfactory(this,"ArgumentDeclarationList_2",new SCreator(ArgumentDeclarationList_2_factory)); 13003new Sfactory(this,"ArgumentDeclarationList_2",new SCreator(ArgumentDeclarationList_2_factory));
10859new Sfactory(this,"ArgumentDeclarationList_3",new SCreator(ArgumentDeclarationList_3_factory));
10860new Sfactory(this,"GlobalDefinitions_1",new SCreator(GlobalDefinitions_1_factory)); 13004new Sfactory(this,"GlobalDefinitions_1",new SCreator(GlobalDefinitions_1_factory));
10861new Sfactory(this,"GlobalDefinitions_2",new SCreator(GlobalDefinitions_2_factory)); 13005new Sfactory(this,"GlobalDefinitions_2",new SCreator(GlobalDefinitions_2_factory));
10862new Sfactory(this,"IncrementDecrementExpression",new SCreator(IncrementDecrementExpression_factory)); 13006new Sfactory(this,"IncrementDecrementExpression",new SCreator(IncrementDecrementExpression_factory));
10863new Sfactory(this,"GlobalVariableDeclaration",new SCreator(GlobalVariableDeclaration_factory)); 13007new Sfactory(this,"GlobalVariableDeclaration",new SCreator(GlobalVariableDeclaration_factory));
10864new Sfactory(this,"Event_11",new SCreator(Event_11_factory)); 13008new Sfactory(this,"IntArgumentDeclarationList_1",new SCreator(IntArgumentDeclarationList_1_factory));
13009new Sfactory(this,"IntDeclaration_1",new SCreator(IntDeclaration_1_factory));
13010new Sfactory(this,"ArgumentDeclarationList_5",new SCreator(ArgumentDeclarationList_5_factory));
13011new Sfactory(this,"IntVecVecArgumentDeclarationList",new SCreator(IntVecVecArgumentDeclarationList_factory));
13012new Sfactory(this,"VectorArgumentDeclarationList_1",new SCreator(VectorArgumentDeclarationList_1_factory));
13013new Sfactory(this,"KeyArgumentDeclarationList",new SCreator(KeyArgumentDeclarationList_factory));
10865new Sfactory(this,"TypecastExpression_2",new SCreator(TypecastExpression_2_factory)); 13014new Sfactory(this,"TypecastExpression_2",new SCreator(TypecastExpression_2_factory));
10866new Sfactory(this,"TypecastExpression_3",new SCreator(TypecastExpression_3_factory)); 13015new Sfactory(this,"KeyArgStateEvent",new SCreator(KeyArgStateEvent_factory));
10867new Sfactory(this,"TypecastExpression_5",new SCreator(TypecastExpression_5_factory)); 13016new Sfactory(this,"TypecastExpression_5",new SCreator(TypecastExpression_5_factory));
10868new Sfactory(this,"TypecastExpression_8",new SCreator(TypecastExpression_8_factory)); 13017new Sfactory(this,"TypecastExpression_8",new SCreator(TypecastExpression_8_factory));
10869new Sfactory(this,"Constant_1",new SCreator(Constant_1_factory)); 13018new Sfactory(this,"Constant_1",new SCreator(Constant_1_factory));
10870new Sfactory(this,"Expression",new SCreator(Expression_factory)); 13019new Sfactory(this,"Expression",new SCreator(Expression_factory));
10871new Sfactory(this,"Constant_3",new SCreator(Constant_3_factory)); 13020new Sfactory(this,"Constant_3",new SCreator(Constant_3_factory));
10872new Sfactory(this,"Constant_4",new SCreator(Constant_4_factory)); 13021new Sfactory(this,"Constant_4",new SCreator(Constant_4_factory));
13022new Sfactory(this,"IntArgEvent_5",new SCreator(IntArgEvent_5_factory));
10873new Sfactory(this,"BinaryExpression_1",new SCreator(BinaryExpression_1_factory)); 13023new Sfactory(this,"BinaryExpression_1",new SCreator(BinaryExpression_1_factory));
10874new Sfactory(this,"IfStatement_2",new SCreator(IfStatement_2_factory)); 13024new Sfactory(this,"IfStatement_2",new SCreator(IfStatement_2_factory));
10875new Sfactory(this,"IfStatement_3",new SCreator(IfStatement_3_factory)); 13025new Sfactory(this,"IfStatement_3",new SCreator(IfStatement_3_factory));
10876new Sfactory(this,"IfStatement_4",new SCreator(IfStatement_4_factory)); 13026new Sfactory(this,"KeyArgEvent",new SCreator(KeyArgEvent_factory));
10877new Sfactory(this,"ReturnStatement",new SCreator(ReturnStatement_factory));
10878new Sfactory(this,"Event_2",new SCreator(Event_2_factory)); 13027new Sfactory(this,"Event_2",new SCreator(Event_2_factory));
13028new Sfactory(this,"JumpLabel_1",new SCreator(JumpLabel_1_factory));
10879new Sfactory(this,"RotationConstant",new SCreator(RotationConstant_factory)); 13029new Sfactory(this,"RotationConstant",new SCreator(RotationConstant_factory));
10880new Sfactory(this,"Statement_12",new SCreator(Statement_12_factory)); 13030new Sfactory(this,"Statement_12",new SCreator(Statement_12_factory));
13031new Sfactory(this,"Statement_13",new SCreator(Statement_13_factory));
10881new Sfactory(this,"UnaryExpression_1",new SCreator(UnaryExpression_1_factory)); 13032new Sfactory(this,"UnaryExpression_1",new SCreator(UnaryExpression_1_factory));
10882new Sfactory(this,"UnaryExpression_2",new SCreator(UnaryExpression_2_factory)); 13033new Sfactory(this,"UnaryExpression_2",new SCreator(UnaryExpression_2_factory));
10883new Sfactory(this,"UnaryExpression_3",new SCreator(UnaryExpression_3_factory)); 13034new Sfactory(this,"UnaryExpression_3",new SCreator(UnaryExpression_3_factory));
10884new Sfactory(this,"ArgumentList_1",new SCreator(ArgumentList_1_factory)); 13035new Sfactory(this,"ArgumentList_1",new SCreator(ArgumentList_1_factory));
10885new Sfactory(this,"ArgumentList_2",new SCreator(ArgumentList_2_factory)); 13036new Sfactory(this,"KeyIntIntArgEvent",new SCreator(KeyIntIntArgEvent_factory));
13037new Sfactory(this,"ArgumentList_3",new SCreator(ArgumentList_3_factory));
10886new Sfactory(this,"Constant",new SCreator(Constant_factory)); 13038new Sfactory(this,"Constant",new SCreator(Constant_factory));
10887new Sfactory(this,"State",new SCreator(State_factory)); 13039new Sfactory(this,"State",new SCreator(State_factory));
10888new Sfactory(this,"Event_13",new SCreator(Event_13_factory)); 13040new Sfactory(this,"StateBody_13",new SCreator(StateBody_13_factory));
13041new Sfactory(this,"KeyArgStateEvent_1",new SCreator(KeyArgStateEvent_1_factory));
13042new Sfactory(this,"SimpleAssignment_8",new SCreator(SimpleAssignment_8_factory));
10889new Sfactory(this,"LSLProgramRoot",new SCreator(LSLProgramRoot_factory)); 13043new Sfactory(this,"LSLProgramRoot",new SCreator(LSLProgramRoot_factory));
10890new Sfactory(this,"StateChange",new SCreator(StateChange_factory)); 13044new Sfactory(this,"StateChange",new SCreator(StateChange_factory));
10891new Sfactory(this,"IncrementDecrementExpression_2",new SCreator(IncrementDecrementExpression_2_factory)); 13045new Sfactory(this,"VecDeclaration_1",new SCreator(VecDeclaration_1_factory));
10892new Sfactory(this,"GlobalVariableDeclaration_1",new SCreator(GlobalVariableDeclaration_1_factory)); 13046new Sfactory(this,"GlobalVariableDeclaration_1",new SCreator(GlobalVariableDeclaration_1_factory));
10893new Sfactory(this,"GlobalVariableDeclaration_2",new SCreator(GlobalVariableDeclaration_2_factory)); 13047new Sfactory(this,"GlobalVariableDeclaration_2",new SCreator(GlobalVariableDeclaration_2_factory));
10894new Sfactory(this,"IncrementDecrementExpression_5",new SCreator(IncrementDecrementExpression_5_factory)); 13048new Sfactory(this,"IncrementDecrementExpression_5",new SCreator(IncrementDecrementExpression_5_factory));
10895new Sfactory(this,"GlobalFunctionDefinition_2",new SCreator(GlobalFunctionDefinition_2_factory)); 13049new Sfactory(this,"ReturnStatement",new SCreator(ReturnStatement_factory));
10896new Sfactory(this,"IncrementDecrementExpression_7",new SCreator(IncrementDecrementExpression_7_factory)); 13050new Sfactory(this,"StateBody_10",new SCreator(StateBody_10_factory));
10897new Sfactory(this,"IncrementDecrementExpression_8",new SCreator(IncrementDecrementExpression_8_factory)); 13051new Sfactory(this,"StateBody_11",new SCreator(StateBody_11_factory));
10898new Sfactory(this,"Assignment_1",new SCreator(Assignment_1_factory)); 13052new Sfactory(this,"StateBody_12",new SCreator(StateBody_12_factory));
10899new Sfactory(this,"Event_21",new SCreator(Event_21_factory)); 13053new Sfactory(this,"IntVecVecArgStateEvent_1",new SCreator(IntVecVecArgStateEvent_1_factory));
10900new Sfactory(this,"Event_22",new SCreator(Event_22_factory)); 13054new Sfactory(this,"KeyDeclaration",new SCreator(KeyDeclaration_factory));
13055new Sfactory(this,"IntArgEvent_6",new SCreator(IntArgEvent_6_factory));
13056new Sfactory(this,"ArgumentDeclarationList_3",new SCreator(ArgumentDeclarationList_3_factory));
13057new Sfactory(this,"ArgumentList_2",new SCreator(ArgumentList_2_factory));
13058new Sfactory(this,"IntArgEvent_10",new SCreator(IntArgEvent_10_factory));
10901new Sfactory(this,"CompoundStatement",new SCreator(CompoundStatement_factory)); 13059new Sfactory(this,"CompoundStatement",new SCreator(CompoundStatement_factory));
10902new Sfactory(this,"RotationConstant_1",new SCreator(RotationConstant_1_factory)); 13060new Sfactory(this,"TypecastExpression_3",new SCreator(TypecastExpression_3_factory));
10903new Sfactory(this,"TypecastExpression",new SCreator(TypecastExpression_factory)); 13061new Sfactory(this,"IntArgumentDeclarationList",new SCreator(IntArgumentDeclarationList_factory));
13062new Sfactory(this,"ArgumentDeclarationList_4",new SCreator(ArgumentDeclarationList_4_factory));
10904new Sfactory(this,"SimpleAssignment_3",new SCreator(SimpleAssignment_3_factory)); 13063new Sfactory(this,"SimpleAssignment_3",new SCreator(SimpleAssignment_3_factory));
10905new Sfactory(this,"SimpleAssignment_4",new SCreator(SimpleAssignment_4_factory)); 13064new Sfactory(this,"SimpleAssignment_4",new SCreator(SimpleAssignment_4_factory));
10906new Sfactory(this,"Statement_1",new SCreator(Statement_1_factory)); 13065new Sfactory(this,"Statement_1",new SCreator(Statement_1_factory));
10907new Sfactory(this,"Statement_2",new SCreator(Statement_2_factory)); 13066new Sfactory(this,"Statement_2",new SCreator(Statement_2_factory));
10908new Sfactory(this,"Statement_3",new SCreator(Statement_3_factory));
10909new Sfactory(this,"Statement_4",new SCreator(Statement_4_factory)); 13067new Sfactory(this,"Statement_4",new SCreator(Statement_4_factory));
10910new Sfactory(this,"Statement_5",new SCreator(Statement_5_factory)); 13068new Sfactory(this,"Statement_5",new SCreator(Statement_5_factory));
10911new Sfactory(this,"Statement_6",new SCreator(Statement_6_factory)); 13069new Sfactory(this,"Statement_6",new SCreator(Statement_6_factory));
10912new Sfactory(this,"Statement_7",new SCreator(Statement_7_factory));
10913new Sfactory(this,"Statement_8",new SCreator(Statement_8_factory)); 13070new Sfactory(this,"Statement_8",new SCreator(Statement_8_factory));
10914new Sfactory(this,"Statement_9",new SCreator(Statement_9_factory)); 13071new Sfactory(this,"Statement_9",new SCreator(Statement_9_factory));
10915new Sfactory(this,"ExpressionArgument",new SCreator(ExpressionArgument_factory)); 13072new Sfactory(this,"ExpressionArgument",new SCreator(ExpressionArgument_factory));
@@ -10922,27 +13079,35 @@ new Sfactory(this,"StateBody",new SCreator(StateBody_factory));
10922new Sfactory(this,"Event_7",new SCreator(Event_7_factory)); 13079new Sfactory(this,"Event_7",new SCreator(Event_7_factory));
10923new Sfactory(this,"Event_8",new SCreator(Event_8_factory)); 13080new Sfactory(this,"Event_8",new SCreator(Event_8_factory));
10924new Sfactory(this,"IncrementDecrementExpression_1",new SCreator(IncrementDecrementExpression_1_factory)); 13081new Sfactory(this,"IncrementDecrementExpression_1",new SCreator(IncrementDecrementExpression_1_factory));
10925new Sfactory(this,"IncrementDecrementExpression_3",new SCreator(IncrementDecrementExpression_3_factory)); 13082new Sfactory(this,"IncrementDecrementExpression_2",new SCreator(IncrementDecrementExpression_2_factory));
13083new Sfactory(this,"IntVecVecArgumentDeclarationList_1",new SCreator(IntVecVecArgumentDeclarationList_1_factory));
10926new Sfactory(this,"IncrementDecrementExpression_4",new SCreator(IncrementDecrementExpression_4_factory)); 13084new Sfactory(this,"IncrementDecrementExpression_4",new SCreator(IncrementDecrementExpression_4_factory));
10927new Sfactory(this,"IncrementDecrementExpression_6",new SCreator(IncrementDecrementExpression_6_factory)); 13085new Sfactory(this,"IncrementDecrementExpression_6",new SCreator(IncrementDecrementExpression_6_factory));
13086new Sfactory(this,"IncrementDecrementExpression_7",new SCreator(IncrementDecrementExpression_7_factory));
10928new Sfactory(this,"StateEvent",new SCreator(StateEvent_factory)); 13087new Sfactory(this,"StateEvent",new SCreator(StateEvent_factory));
10929new Sfactory(this,"Event_20",new SCreator(Event_20_factory)); 13088new Sfactory(this,"IntArgEvent_3",new SCreator(IntArgEvent_3_factory));
10930new Sfactory(this,"Event_23",new SCreator(Event_23_factory)); 13089new Sfactory(this,"IntArgEvent_4",new SCreator(IntArgEvent_4_factory));
10931new Sfactory(this,"Event_24",new SCreator(Event_24_factory)); 13090new Sfactory(this,"KeyDeclaration_1",new SCreator(KeyDeclaration_1_factory));
10932new Sfactory(this,"Event_26",new SCreator(Event_26_factory)); 13091new Sfactory(this,"Statement_3",new SCreator(Statement_3_factory));
13092new Sfactory(this,"IntArgEvent_7",new SCreator(IntArgEvent_7_factory));
13093new Sfactory(this,"IntArgEvent_8",new SCreator(IntArgEvent_8_factory));
10933new Sfactory(this,"SimpleAssignment_10",new SCreator(SimpleAssignment_10_factory)); 13094new Sfactory(this,"SimpleAssignment_10",new SCreator(SimpleAssignment_10_factory));
13095new Sfactory(this,"StatementList_2",new SCreator(StatementList_2_factory));
13096new Sfactory(this,"IntRotRotArgStateEvent_1",new SCreator(IntRotRotArgStateEvent_1_factory));
13097new Sfactory(this,"VectorArgEvent_2",new SCreator(VectorArgEvent_2_factory));
10934new Sfactory(this,"Event",new SCreator(Event_factory)); 13098new Sfactory(this,"Event",new SCreator(Event_factory));
10935new Sfactory(this,"SimpleAssignment_14",new SCreator(SimpleAssignment_14_factory)); 13099new Sfactory(this,"SimpleAssignment_14",new SCreator(SimpleAssignment_14_factory));
10936new Sfactory(this,"SimpleAssignment_16",new SCreator(SimpleAssignment_16_factory)); 13100new Sfactory(this,"SimpleAssignment_16",new SCreator(SimpleAssignment_16_factory));
13101new Sfactory(this,"SimpleAssignment_17",new SCreator(SimpleAssignment_17_factory));
13102new Sfactory(this,"SimpleAssignment_18",new SCreator(SimpleAssignment_18_factory));
10937new Sfactory(this,"Statement_10",new SCreator(Statement_10_factory)); 13103new Sfactory(this,"Statement_10",new SCreator(Statement_10_factory));
10938new Sfactory(this,"Statement_11",new SCreator(Statement_11_factory)); 13104new Sfactory(this,"Statement_11",new SCreator(Statement_11_factory));
10939new Sfactory(this,"SimpleAssignment",new SCreator(SimpleAssignment_factory)); 13105new Sfactory(this,"SimpleAssignment",new SCreator(SimpleAssignment_factory));
10940new Sfactory(this,"Statement_13",new SCreator(Statement_13_factory)); 13106new Sfactory(this,"TypecastExpression",new SCreator(TypecastExpression_factory));
10941new Sfactory(this,"Event_15",new SCreator(Event_15_factory)); 13107new Sfactory(this,"JumpStatement_1",new SCreator(JumpStatement_1_factory));
10942new Sfactory(this,"Event_16",new SCreator(Event_16_factory));
10943new Sfactory(this,"Event_32",new SCreator(Event_32_factory));
10944new Sfactory(this,"Event_34",new SCreator(Event_34_factory));
10945new Sfactory(this,"SimpleAssignment_20",new SCreator(SimpleAssignment_20_factory)); 13108new Sfactory(this,"SimpleAssignment_20",new SCreator(SimpleAssignment_20_factory));
13109new Sfactory(this,"Statement_7",new SCreator(Statement_7_factory));
13110new Sfactory(this,"SimpleAssignment_23",new SCreator(SimpleAssignment_23_factory));
10946new Sfactory(this,"SimpleAssignment_24",new SCreator(SimpleAssignment_24_factory)); 13111new Sfactory(this,"SimpleAssignment_24",new SCreator(SimpleAssignment_24_factory));
10947new Sfactory(this,"SimpleAssignment_1",new SCreator(SimpleAssignment_1_factory)); 13112new Sfactory(this,"SimpleAssignment_1",new SCreator(SimpleAssignment_1_factory));
10948new Sfactory(this,"SimpleAssignment_2",new SCreator(SimpleAssignment_2_factory)); 13113new Sfactory(this,"SimpleAssignment_2",new SCreator(SimpleAssignment_2_factory));
@@ -10950,73 +13115,90 @@ new Sfactory(this,"BinaryExpression",new SCreator(BinaryExpression_factory));
10950new Sfactory(this,"FunctionCallExpression",new SCreator(FunctionCallExpression_factory)); 13115new Sfactory(this,"FunctionCallExpression",new SCreator(FunctionCallExpression_factory));
10951new Sfactory(this,"SimpleAssignment_6",new SCreator(SimpleAssignment_6_factory)); 13116new Sfactory(this,"SimpleAssignment_6",new SCreator(SimpleAssignment_6_factory));
10952new Sfactory(this,"StateBody_1",new SCreator(StateBody_1_factory)); 13117new Sfactory(this,"StateBody_1",new SCreator(StateBody_1_factory));
10953new Sfactory(this,"StatementList_2",new SCreator(StatementList_2_factory)); 13118new Sfactory(this,"StateBody_2",new SCreator(StateBody_2_factory));
10954new Sfactory(this,"SimpleAssignment_9",new SCreator(SimpleAssignment_9_factory)); 13119new Sfactory(this,"StateBody_3",new SCreator(StateBody_3_factory));
10955new Sfactory(this,"BinaryExpression_15",new SCreator(BinaryExpression_15_factory)); 13120new Sfactory(this,"StateBody_4",new SCreator(StateBody_4_factory));
10956new Sfactory(this,"BinaryExpression_16",new SCreator(BinaryExpression_16_factory)); 13121new Sfactory(this,"StateBody_5",new SCreator(StateBody_5_factory));
10957new Sfactory(this,"BinaryExpression_17",new SCreator(BinaryExpression_17_factory)); 13122new Sfactory(this,"StateBody_6",new SCreator(StateBody_6_factory));
10958new Sfactory(this,"BinaryExpression_18",new SCreator(BinaryExpression_18_factory)); 13123new Sfactory(this,"StateBody_7",new SCreator(StateBody_7_factory));
10959new Sfactory(this,"Event_25",new SCreator(Event_25_factory)); 13124new Sfactory(this,"StateBody_8",new SCreator(StateBody_8_factory));
10960new Sfactory(this,"Event_9",new SCreator(Event_9_factory)); 13125new Sfactory(this,"StateBody_9",new SCreator(StateBody_9_factory));
10961new Sfactory(this,"Statement",new SCreator(Statement_factory)); 13126new Sfactory(this,"Statement",new SCreator(Statement_factory));
13127new Sfactory(this,"IncrementDecrementExpression_3",new SCreator(IncrementDecrementExpression_3_factory));
10962new Sfactory(this,"JumpStatement",new SCreator(JumpStatement_factory)); 13128new Sfactory(this,"JumpStatement",new SCreator(JumpStatement_factory));
10963new Sfactory(this,"BinaryExpression_11",new SCreator(BinaryExpression_11_factory)); 13129new Sfactory(this,"BinaryExpression_11",new SCreator(BinaryExpression_11_factory));
10964new Sfactory(this,"BinaryExpression_12",new SCreator(BinaryExpression_12_factory)); 13130new Sfactory(this,"IntArgEvent",new SCreator(IntArgEvent_factory));
10965new Sfactory(this,"BinaryExpression_13",new SCreator(BinaryExpression_13_factory)); 13131new Sfactory(this,"IncrementDecrementExpression_8",new SCreator(IncrementDecrementExpression_8_factory));
10966new Sfactory(this,"BinaryExpression_14",new SCreator(BinaryExpression_14_factory)); 13132new Sfactory(this,"BinaryExpression_14",new SCreator(BinaryExpression_14_factory));
13133new Sfactory(this,"BinaryExpression_15",new SCreator(BinaryExpression_15_factory));
13134new Sfactory(this,"BinaryExpression_16",new SCreator(BinaryExpression_16_factory));
10967new Sfactory(this,"BinaryExpression_6",new SCreator(BinaryExpression_6_factory)); 13135new Sfactory(this,"BinaryExpression_6",new SCreator(BinaryExpression_6_factory));
10968new Sfactory(this,"BinaryExpression_7",new SCreator(BinaryExpression_7_factory)); 13136new Sfactory(this,"BinaryExpression_7",new SCreator(BinaryExpression_7_factory));
13137new Sfactory(this,"Typename_2",new SCreator(Typename_2_factory));
13138new Sfactory(this,"Typename_4",new SCreator(Typename_4_factory));
10969new Sfactory(this,"ArgumentList",new SCreator(ArgumentList_factory)); 13139new Sfactory(this,"ArgumentList",new SCreator(ArgumentList_factory));
10970new Sfactory(this,"Event_10",new SCreator(Event_10_factory)); 13140new Sfactory(this,"BinaryExpression_12",new SCreator(BinaryExpression_12_factory));
10971new Sfactory(this,"ConstantExpression_1",new SCreator(ConstantExpression_1_factory)); 13141new Sfactory(this,"BinaryExpression_13",new SCreator(BinaryExpression_13_factory));
10972new Sfactory(this,"Event_12",new SCreator(Event_12_factory)); 13142new Sfactory(this,"GlobalFunctionDefinition_2",new SCreator(GlobalFunctionDefinition_2_factory));
10973new Sfactory(this,"Event_14",new SCreator(Event_14_factory)); 13143new Sfactory(this,"StateChange_2",new SCreator(StateChange_2_factory));
10974new Sfactory(this,"Event_17",new SCreator(Event_17_factory)); 13144new Sfactory(this,"VoidArgEvent_1",new SCreator(VoidArgEvent_1_factory));
10975new Sfactory(this,"Event_18",new SCreator(Event_18_factory));
10976new Sfactory(this,"Event_19",new SCreator(Event_19_factory));
10977new Sfactory(this,"BinaryExpression_10",new SCreator(BinaryExpression_10_factory)); 13145new Sfactory(this,"BinaryExpression_10",new SCreator(BinaryExpression_10_factory));
13146new Sfactory(this,"VoidArgEvent_5",new SCreator(VoidArgEvent_5_factory));
13147new Sfactory(this,"VoidArgEvent_6",new SCreator(VoidArgEvent_6_factory));
13148new Sfactory(this,"VoidArgEvent_7",new SCreator(VoidArgEvent_7_factory));
13149new Sfactory(this,"VoidArgEvent_8",new SCreator(VoidArgEvent_8_factory));
13150new Sfactory(this,"BinaryExpression_17",new SCreator(BinaryExpression_17_factory));
10978new Sfactory(this,"StateEvent_1",new SCreator(StateEvent_1_factory)); 13151new Sfactory(this,"StateEvent_1",new SCreator(StateEvent_1_factory));
10979new Sfactory(this,"VectorConstant",new SCreator(VectorConstant_factory)); 13152new Sfactory(this,"VectorConstant",new SCreator(VectorConstant_factory));
10980new Sfactory(this,"EmptyStatement_1",new SCreator(EmptyStatement_1_factory)); 13153new Sfactory(this,"VectorArgEvent_1",new SCreator(VectorArgEvent_1_factory));
13154new Sfactory(this,"IntDeclaration",new SCreator(IntDeclaration_factory));
13155new Sfactory(this,"VectorArgEvent_3",new SCreator(VectorArgEvent_3_factory));
10981new Sfactory(this,"TypecastExpression_4",new SCreator(TypecastExpression_4_factory)); 13156new Sfactory(this,"TypecastExpression_4",new SCreator(TypecastExpression_4_factory));
10982new Sfactory(this,"TypecastExpression_6",new SCreator(TypecastExpression_6_factory)); 13157new Sfactory(this,"TypecastExpression_6",new SCreator(TypecastExpression_6_factory));
10983new Sfactory(this,"TypecastExpression_7",new SCreator(TypecastExpression_7_factory)); 13158new Sfactory(this,"TypecastExpression_7",new SCreator(TypecastExpression_7_factory));
10984new Sfactory(this,"FunctionCall",new SCreator(FunctionCall_factory)); 13159new Sfactory(this,"FunctionCall",new SCreator(FunctionCall_factory));
10985new Sfactory(this,"Event_27",new SCreator(Event_27_factory));
10986new Sfactory(this,"Event_28",new SCreator(Event_28_factory));
10987new Sfactory(this,"Event_29",new SCreator(Event_29_factory));
10988new Sfactory(this,"ListConstant_1",new SCreator(ListConstant_1_factory)); 13160new Sfactory(this,"ListConstant_1",new SCreator(ListConstant_1_factory));
13161new Sfactory(this,"BinaryExpression_18",new SCreator(BinaryExpression_18_factory));
10989new Sfactory(this,"Event_6",new SCreator(Event_6_factory)); 13162new Sfactory(this,"Event_6",new SCreator(Event_6_factory));
13163new Sfactory(this,"KeyArgEvent_2",new SCreator(KeyArgEvent_2_factory));
10990new Sfactory(this,"Declaration_1",new SCreator(Declaration_1_factory)); 13164new Sfactory(this,"Declaration_1",new SCreator(Declaration_1_factory));
13165new Sfactory(this,"EmptyStatement_1",new SCreator(EmptyStatement_1_factory));
10991new Sfactory(this,"SimpleAssignment_7",new SCreator(SimpleAssignment_7_factory)); 13166new Sfactory(this,"SimpleAssignment_7",new SCreator(SimpleAssignment_7_factory));
10992new Sfactory(this,"ForLoop",new SCreator(ForLoop_factory)); 13167new Sfactory(this,"ForLoop",new SCreator(ForLoop_factory));
10993new Sfactory(this,"ForLoop_2",new SCreator(ForLoop_2_factory)); 13168new Sfactory(this,"ForLoop_2",new SCreator(ForLoop_2_factory));
10994new Sfactory(this,"Event_30",new SCreator(Event_30_factory)); 13169new Sfactory(this,"KeyIntIntArgStateEvent_1",new SCreator(KeyIntIntArgStateEvent_1_factory));
10995new Sfactory(this,"Event_31",new SCreator(Event_31_factory)); 13170new Sfactory(this,"KeyArgumentDeclarationList_1",new SCreator(KeyArgumentDeclarationList_1_factory));
10996new Sfactory(this,"Event_33",new SCreator(Event_33_factory));
10997new Sfactory(this,"GlobalFunctionDefinition_1",new SCreator(GlobalFunctionDefinition_1_factory)); 13171new Sfactory(this,"GlobalFunctionDefinition_1",new SCreator(GlobalFunctionDefinition_1_factory));
10998new Sfactory(this,"JumpLabel_1",new SCreator(JumpLabel_1_factory));
10999new Sfactory(this,"IfStatement",new SCreator(IfStatement_factory)); 13172new Sfactory(this,"IfStatement",new SCreator(IfStatement_factory));
11000new Sfactory(this,"ForLoopStatement_1",new SCreator(ForLoopStatement_1_factory)); 13173new Sfactory(this,"ForLoopStatement_1",new SCreator(ForLoopStatement_1_factory));
11001new Sfactory(this,"ForLoopStatement_2",new SCreator(ForLoopStatement_2_factory)); 13174new Sfactory(this,"ForLoopStatement_2",new SCreator(ForLoopStatement_2_factory));
11002new Sfactory(this,"ForLoopStatement_3",new SCreator(ForLoopStatement_3_factory)); 13175new Sfactory(this,"ForLoopStatement_3",new SCreator(ForLoopStatement_3_factory));
11003new Sfactory(this,"ArgumentDeclarationList_4",new SCreator(ArgumentDeclarationList_4_factory)); 13176new Sfactory(this,"IntRotRotArgumentDeclarationList",new SCreator(IntRotRotArgumentDeclarationList_factory));
11004new Sfactory(this,"ArgumentDeclarationList_5",new SCreator(ArgumentDeclarationList_5_factory)); 13177new Sfactory(this,"IntArgEvent_1",new SCreator(IntArgEvent_1_factory));
11005new Sfactory(this,"EmptyStatement",new SCreator(EmptyStatement_factory)); 13178new Sfactory(this,"IntArgEvent_2",new SCreator(IntArgEvent_2_factory));
11006new Sfactory(this,"WhileStatement",new SCreator(WhileStatement_factory)); 13179new Sfactory(this,"WhileStatement",new SCreator(WhileStatement_factory));
11007new Sfactory(this,"ForLoop_1",new SCreator(ForLoop_1_factory)); 13180new Sfactory(this,"ForLoop_1",new SCreator(ForLoop_1_factory));
11008new Sfactory(this,"Constant_2",new SCreator(Constant_2_factory)); 13181new Sfactory(this,"Constant_2",new SCreator(Constant_2_factory));
11009new Sfactory(this,"StatementList",new SCreator(StatementList_factory)); 13182new Sfactory(this,"VoidArgEvent",new SCreator(VoidArgEvent_factory));
11010new Sfactory(this,"StateBody_2",new SCreator(StateBody_2_factory)); 13183new Sfactory(this,"RotDeclaration",new SCreator(RotDeclaration_factory));
13184new Sfactory(this,"WhileStatement_1",new SCreator(WhileStatement_1_factory));
11011new Sfactory(this,"WhileStatement_2",new SCreator(WhileStatement_2_factory)); 13185new Sfactory(this,"WhileStatement_2",new SCreator(WhileStatement_2_factory));
13186new Sfactory(this,"VectorArgStateEvent_1",new SCreator(VectorArgStateEvent_1_factory));
11012new Sfactory(this,"IdentExpression_1",new SCreator(IdentExpression_1_factory)); 13187new Sfactory(this,"IdentExpression_1",new SCreator(IdentExpression_1_factory));
13188new Sfactory(this,"VectorArgumentDeclarationList",new SCreator(VectorArgumentDeclarationList_factory));
11013new Sfactory(this,"States",new SCreator(States_factory)); 13189new Sfactory(this,"States",new SCreator(States_factory));
13190new Sfactory(this,"VoidArgStateEvent",new SCreator(VoidArgStateEvent_factory));
11014} 13191}
11015public static object ExpressionArgument_1_factory(Parser yyp) { return new ExpressionArgument_1(yyp); } 13192public static object ExpressionArgument_1_factory(Parser yyp) { return new ExpressionArgument_1(yyp); }
11016public static object SimpleAssignment_8_factory(Parser yyp) { return new SimpleAssignment_8(yyp); } 13193public static object VectorArgStateEvent_factory(Parser yyp) { return new VectorArgStateEvent(yyp); }
13194public static object IntVecVecArgStateEvent_factory(Parser yyp) { return new IntVecVecArgStateEvent(yyp); }
13195public static object IntArgStateEvent_1_factory(Parser yyp) { return new IntArgStateEvent_1(yyp); }
13196public static object SimpleAssignment_9_factory(Parser yyp) { return new SimpleAssignment_9(yyp); }
11017public static object StatementList_1_factory(Parser yyp) { return new StatementList_1(yyp); } 13197public static object StatementList_1_factory(Parser yyp) { return new StatementList_1(yyp); }
13198public static object RotDeclaration_1_factory(Parser yyp) { return new RotDeclaration_1(yyp); }
13199public static object IntRotRotArgEvent_1_factory(Parser yyp) { return new IntRotRotArgEvent_1(yyp); }
11018public static object StateChange_1_factory(Parser yyp) { return new StateChange_1(yyp); } 13200public static object StateChange_1_factory(Parser yyp) { return new StateChange_1(yyp); }
11019public static object StateChange_2_factory(Parser yyp) { return new StateChange_2(yyp); } 13201public static object EmptyStatement_factory(Parser yyp) { return new EmptyStatement(yyp); }
11020public static object Declaration_factory(Parser yyp) { return new Declaration(yyp); } 13202public static object Declaration_factory(Parser yyp) { return new Declaration(yyp); }
11021public static object IdentExpression_factory(Parser yyp) { return new IdentExpression(yyp); } 13203public static object IdentExpression_factory(Parser yyp) { return new IdentExpression(yyp); }
11022public static object error_factory(Parser yyp) { return new error(yyp); } 13204public static object error_factory(Parser yyp) { return new error(yyp); }
@@ -11029,20 +13211,25 @@ public static object SimpleAssignment_19_factory(Parser yyp) { return new Simple
11029public static object BinaryExpression_9_factory(Parser yyp) { return new BinaryExpression_9(yyp); } 13211public static object BinaryExpression_9_factory(Parser yyp) { return new BinaryExpression_9(yyp); }
11030public static object VectorConstant_1_factory(Parser yyp) { return new VectorConstant_1(yyp); } 13212public static object VectorConstant_1_factory(Parser yyp) { return new VectorConstant_1(yyp); }
11031public static object ParenthesisExpression_factory(Parser yyp) { return new ParenthesisExpression(yyp); } 13213public static object ParenthesisExpression_factory(Parser yyp) { return new ParenthesisExpression(yyp); }
13214public static object StatementList_factory(Parser yyp) { return new StatementList(yyp); }
13215public static object IntRotRotArgEvent_factory(Parser yyp) { return new IntRotRotArgEvent(yyp); }
11032public static object UnaryExpression_factory(Parser yyp) { return new UnaryExpression(yyp); } 13216public static object UnaryExpression_factory(Parser yyp) { return new UnaryExpression(yyp); }
11033public static object IdentDotExpression_1_factory(Parser yyp) { return new IdentDotExpression_1(yyp); } 13217public static object IdentDotExpression_1_factory(Parser yyp) { return new IdentDotExpression_1(yyp); }
11034public static object ArgumentList_4_factory(Parser yyp) { return new ArgumentList_4(yyp); } 13218public static object ArgumentList_4_factory(Parser yyp) { return new ArgumentList_4(yyp); }
11035public static object Typename_factory(Parser yyp) { return new Typename(yyp); } 13219public static object Typename_factory(Parser yyp) { return new Typename(yyp); }
11036public static object IfStatement_1_factory(Parser yyp) { return new IfStatement_1(yyp); } 13220public static object IfStatement_1_factory(Parser yyp) { return new IfStatement_1(yyp); }
13221public static object RotationConstant_1_factory(Parser yyp) { return new RotationConstant_1(yyp); }
11037public static object Assignment_factory(Parser yyp) { return new Assignment(yyp); } 13222public static object Assignment_factory(Parser yyp) { return new Assignment(yyp); }
13223public static object IfStatement_4_factory(Parser yyp) { return new IfStatement_4(yyp); }
11038public static object CompoundStatement_1_factory(Parser yyp) { return new CompoundStatement_1(yyp); } 13224public static object CompoundStatement_1_factory(Parser yyp) { return new CompoundStatement_1(yyp); }
11039public static object CompoundStatement_2_factory(Parser yyp) { return new CompoundStatement_2(yyp); } 13225public static object CompoundStatement_2_factory(Parser yyp) { return new CompoundStatement_2(yyp); }
13226public static object KeyIntIntArgumentDeclarationList_1_factory(Parser yyp) { return new KeyIntIntArgumentDeclarationList_1(yyp); }
11040public static object BinaryExpression_8_factory(Parser yyp) { return new BinaryExpression_8(yyp); } 13227public static object BinaryExpression_8_factory(Parser yyp) { return new BinaryExpression_8(yyp); }
13228public static object VectorArgEvent_factory(Parser yyp) { return new VectorArgEvent(yyp); }
11041public static object ReturnStatement_1_factory(Parser yyp) { return new ReturnStatement_1(yyp); } 13229public static object ReturnStatement_1_factory(Parser yyp) { return new ReturnStatement_1(yyp); }
11042public static object IdentDotExpression_factory(Parser yyp) { return new IdentDotExpression(yyp); } 13230public static object IdentDotExpression_factory(Parser yyp) { return new IdentDotExpression(yyp); }
11043public static object Argument_factory(Parser yyp) { return new Argument(yyp); } 13231public static object Argument_factory(Parser yyp) { return new Argument(yyp); }
11044public static object State_2_factory(Parser yyp) { return new State_2(yyp); } 13232public static object State_2_factory(Parser yyp) { return new State_2(yyp); }
11045public static object WhileStatement_1_factory(Parser yyp) { return new WhileStatement_1(yyp); }
11046public static object GlobalDefinitions_3_factory(Parser yyp) { return new GlobalDefinitions_3(yyp); } 13233public static object GlobalDefinitions_3_factory(Parser yyp) { return new GlobalDefinitions_3(yyp); }
11047public static object GlobalDefinitions_4_factory(Parser yyp) { return new GlobalDefinitions_4(yyp); } 13234public static object GlobalDefinitions_4_factory(Parser yyp) { return new GlobalDefinitions_4(yyp); }
11048public static object Event_1_factory(Parser yyp) { return new Event_1(yyp); } 13235public static object Event_1_factory(Parser yyp) { return new Event_1(yyp); }
@@ -11052,9 +13239,9 @@ public static object Event_4_factory(Parser yyp) { return new Event_4(yyp); }
11052public static object Event_5_factory(Parser yyp) { return new Event_5(yyp); } 13239public static object Event_5_factory(Parser yyp) { return new Event_5(yyp); }
11053public static object SimpleAssignment_5_factory(Parser yyp) { return new SimpleAssignment_5(yyp); } 13240public static object SimpleAssignment_5_factory(Parser yyp) { return new SimpleAssignment_5(yyp); }
11054public static object Typename_1_factory(Parser yyp) { return new Typename_1(yyp); } 13241public static object Typename_1_factory(Parser yyp) { return new Typename_1(yyp); }
11055public static object Typename_2_factory(Parser yyp) { return new Typename_2(yyp); } 13242public static object VoidArgStateEvent_1_factory(Parser yyp) { return new VoidArgStateEvent_1(yyp); }
11056public static object Typename_3_factory(Parser yyp) { return new Typename_3(yyp); } 13243public static object Typename_3_factory(Parser yyp) { return new Typename_3(yyp); }
11057public static object Typename_4_factory(Parser yyp) { return new Typename_4(yyp); } 13244public static object IntRotRotArgStateEvent_factory(Parser yyp) { return new IntRotRotArgStateEvent(yyp); }
11058public static object Typename_5_factory(Parser yyp) { return new Typename_5(yyp); } 13245public static object Typename_5_factory(Parser yyp) { return new Typename_5(yyp); }
11059public static object Typename_6_factory(Parser yyp) { return new Typename_6(yyp); } 13246public static object Typename_6_factory(Parser yyp) { return new Typename_6(yyp); }
11060public static object Typename_7_factory(Parser yyp) { return new Typename_7(yyp); } 13247public static object Typename_7_factory(Parser yyp) { return new Typename_7(yyp); }
@@ -11062,10 +13249,16 @@ public static object ArgumentDeclarationList_factory(Parser yyp) { return new Ar
11062public static object ConstantExpression_factory(Parser yyp) { return new ConstantExpression(yyp); } 13249public static object ConstantExpression_factory(Parser yyp) { return new ConstantExpression(yyp); }
11063public static object LSLProgramRoot_1_factory(Parser yyp) { return new LSLProgramRoot_1(yyp); } 13250public static object LSLProgramRoot_1_factory(Parser yyp) { return new LSLProgramRoot_1(yyp); }
11064public static object LSLProgramRoot_2_factory(Parser yyp) { return new LSLProgramRoot_2(yyp); } 13251public static object LSLProgramRoot_2_factory(Parser yyp) { return new LSLProgramRoot_2(yyp); }
13252public static object KeyIntIntArgEvent_1_factory(Parser yyp) { return new KeyIntIntArgEvent_1(yyp); }
11065public static object States_1_factory(Parser yyp) { return new States_1(yyp); } 13253public static object States_1_factory(Parser yyp) { return new States_1(yyp); }
11066public static object States_2_factory(Parser yyp) { return new States_2(yyp); } 13254public static object States_2_factory(Parser yyp) { return new States_2(yyp); }
11067public static object FunctionCallExpression_1_factory(Parser yyp) { return new FunctionCallExpression_1(yyp); } 13255public static object FunctionCallExpression_1_factory(Parser yyp) { return new FunctionCallExpression_1(yyp); }
13256public static object KeyArgEvent_1_factory(Parser yyp) { return new KeyArgEvent_1(yyp); }
11068public static object ForLoopStatement_factory(Parser yyp) { return new ForLoopStatement(yyp); } 13257public static object ForLoopStatement_factory(Parser yyp) { return new ForLoopStatement(yyp); }
13258public static object IntArgStateEvent_factory(Parser yyp) { return new IntArgStateEvent(yyp); }
13259public static object StateBody_15_factory(Parser yyp) { return new StateBody_15(yyp); }
13260public static object IntRotRotArgumentDeclarationList_1_factory(Parser yyp) { return new IntRotRotArgumentDeclarationList_1(yyp); }
13261public static object IntArgEvent_9_factory(Parser yyp) { return new IntArgEvent_9(yyp); }
11069public static object DoWhileStatement_1_factory(Parser yyp) { return new DoWhileStatement_1(yyp); } 13262public static object DoWhileStatement_1_factory(Parser yyp) { return new DoWhileStatement_1(yyp); }
11070public static object DoWhileStatement_2_factory(Parser yyp) { return new DoWhileStatement_2(yyp); } 13263public static object DoWhileStatement_2_factory(Parser yyp) { return new DoWhileStatement_2(yyp); }
11071public static object ForLoopStatement_4_factory(Parser yyp) { return new ForLoopStatement_4(yyp); } 13264public static object ForLoopStatement_4_factory(Parser yyp) { return new ForLoopStatement_4(yyp); }
@@ -11074,74 +13267,93 @@ public static object SimpleAssignment_12_factory(Parser yyp) { return new Simple
11074public static object SimpleAssignment_13_factory(Parser yyp) { return new SimpleAssignment_13(yyp); } 13267public static object SimpleAssignment_13_factory(Parser yyp) { return new SimpleAssignment_13(yyp); }
11075public static object JumpLabel_factory(Parser yyp) { return new JumpLabel(yyp); } 13268public static object JumpLabel_factory(Parser yyp) { return new JumpLabel(yyp); }
11076public static object SimpleAssignment_15_factory(Parser yyp) { return new SimpleAssignment_15(yyp); } 13269public static object SimpleAssignment_15_factory(Parser yyp) { return new SimpleAssignment_15(yyp); }
11077public static object SimpleAssignment_17_factory(Parser yyp) { return new SimpleAssignment_17(yyp); } 13270public static object IntVecVecArgEvent_factory(Parser yyp) { return new IntVecVecArgEvent(yyp); }
11078public static object SimpleAssignment_18_factory(Parser yyp) { return new SimpleAssignment_18(yyp); } 13271public static object VecDeclaration_factory(Parser yyp) { return new VecDeclaration(yyp); }
11079public static object JumpStatement_1_factory(Parser yyp) { return new JumpStatement_1(yyp); } 13272public static object StateBody_14_factory(Parser yyp) { return new StateBody_14(yyp); }
11080public static object GlobalDefinitions_factory(Parser yyp) { return new GlobalDefinitions(yyp); } 13273public static object GlobalDefinitions_factory(Parser yyp) { return new GlobalDefinitions(yyp); }
13274public static object StateBody_16_factory(Parser yyp) { return new StateBody_16(yyp); }
13275public static object KeyIntIntArgumentDeclarationList_factory(Parser yyp) { return new KeyIntIntArgumentDeclarationList(yyp); }
13276public static object ConstantExpression_1_factory(Parser yyp) { return new ConstantExpression_1(yyp); }
13277public static object VoidArgEvent_4_factory(Parser yyp) { return new VoidArgEvent_4(yyp); }
11081public static object FunctionCall_1_factory(Parser yyp) { return new FunctionCall_1(yyp); } 13278public static object FunctionCall_1_factory(Parser yyp) { return new FunctionCall_1(yyp); }
11082public static object ArgumentList_3_factory(Parser yyp) { return new ArgumentList_3(yyp); } 13279public static object Assignment_1_factory(Parser yyp) { return new Assignment_1(yyp); }
11083public static object Assignment_2_factory(Parser yyp) { return new Assignment_2(yyp); } 13280public static object Assignment_2_factory(Parser yyp) { return new Assignment_2(yyp); }
13281public static object IntVecVecArgEvent_1_factory(Parser yyp) { return new IntVecVecArgEvent_1(yyp); }
11084public static object TypecastExpression_1_factory(Parser yyp) { return new TypecastExpression_1(yyp); } 13282public static object TypecastExpression_1_factory(Parser yyp) { return new TypecastExpression_1(yyp); }
11085public static object SimpleAssignment_21_factory(Parser yyp) { return new SimpleAssignment_21(yyp); } 13283public static object SimpleAssignment_21_factory(Parser yyp) { return new SimpleAssignment_21(yyp); }
11086public static object SimpleAssignment_22_factory(Parser yyp) { return new SimpleAssignment_22(yyp); } 13284public static object SimpleAssignment_22_factory(Parser yyp) { return new SimpleAssignment_22(yyp); }
11087public static object SimpleAssignment_23_factory(Parser yyp) { return new SimpleAssignment_23(yyp); } 13285public static object KeyIntIntArgStateEvent_factory(Parser yyp) { return new KeyIntIntArgStateEvent(yyp); }
11088public static object TypecastExpression_9_factory(Parser yyp) { return new TypecastExpression_9(yyp); } 13286public static object TypecastExpression_9_factory(Parser yyp) { return new TypecastExpression_9(yyp); }
13287public static object VoidArgEvent_2_factory(Parser yyp) { return new VoidArgEvent_2(yyp); }
13288public static object VoidArgEvent_3_factory(Parser yyp) { return new VoidArgEvent_3(yyp); }
11089public static object ArgumentDeclarationList_1_factory(Parser yyp) { return new ArgumentDeclarationList_1(yyp); } 13289public static object ArgumentDeclarationList_1_factory(Parser yyp) { return new ArgumentDeclarationList_1(yyp); }
11090public static object ArgumentDeclarationList_2_factory(Parser yyp) { return new ArgumentDeclarationList_2(yyp); } 13290public static object ArgumentDeclarationList_2_factory(Parser yyp) { return new ArgumentDeclarationList_2(yyp); }
11091public static object ArgumentDeclarationList_3_factory(Parser yyp) { return new ArgumentDeclarationList_3(yyp); }
11092public static object GlobalDefinitions_1_factory(Parser yyp) { return new GlobalDefinitions_1(yyp); } 13291public static object GlobalDefinitions_1_factory(Parser yyp) { return new GlobalDefinitions_1(yyp); }
11093public static object GlobalDefinitions_2_factory(Parser yyp) { return new GlobalDefinitions_2(yyp); } 13292public static object GlobalDefinitions_2_factory(Parser yyp) { return new GlobalDefinitions_2(yyp); }
11094public static object IncrementDecrementExpression_factory(Parser yyp) { return new IncrementDecrementExpression(yyp); } 13293public static object IncrementDecrementExpression_factory(Parser yyp) { return new IncrementDecrementExpression(yyp); }
11095public static object GlobalVariableDeclaration_factory(Parser yyp) { return new GlobalVariableDeclaration(yyp); } 13294public static object GlobalVariableDeclaration_factory(Parser yyp) { return new GlobalVariableDeclaration(yyp); }
11096public static object Event_11_factory(Parser yyp) { return new Event_11(yyp); } 13295public static object IntArgumentDeclarationList_1_factory(Parser yyp) { return new IntArgumentDeclarationList_1(yyp); }
13296public static object IntDeclaration_1_factory(Parser yyp) { return new IntDeclaration_1(yyp); }
13297public static object ArgumentDeclarationList_5_factory(Parser yyp) { return new ArgumentDeclarationList_5(yyp); }
13298public static object IntVecVecArgumentDeclarationList_factory(Parser yyp) { return new IntVecVecArgumentDeclarationList(yyp); }
13299public static object VectorArgumentDeclarationList_1_factory(Parser yyp) { return new VectorArgumentDeclarationList_1(yyp); }
13300public static object KeyArgumentDeclarationList_factory(Parser yyp) { return new KeyArgumentDeclarationList(yyp); }
11097public static object TypecastExpression_2_factory(Parser yyp) { return new TypecastExpression_2(yyp); } 13301public static object TypecastExpression_2_factory(Parser yyp) { return new TypecastExpression_2(yyp); }
11098public static object TypecastExpression_3_factory(Parser yyp) { return new TypecastExpression_3(yyp); } 13302public static object KeyArgStateEvent_factory(Parser yyp) { return new KeyArgStateEvent(yyp); }
11099public static object TypecastExpression_5_factory(Parser yyp) { return new TypecastExpression_5(yyp); } 13303public static object TypecastExpression_5_factory(Parser yyp) { return new TypecastExpression_5(yyp); }
11100public static object TypecastExpression_8_factory(Parser yyp) { return new TypecastExpression_8(yyp); } 13304public static object TypecastExpression_8_factory(Parser yyp) { return new TypecastExpression_8(yyp); }
11101public static object Constant_1_factory(Parser yyp) { return new Constant_1(yyp); } 13305public static object Constant_1_factory(Parser yyp) { return new Constant_1(yyp); }
11102public static object Expression_factory(Parser yyp) { return new Expression(yyp); } 13306public static object Expression_factory(Parser yyp) { return new Expression(yyp); }
11103public static object Constant_3_factory(Parser yyp) { return new Constant_3(yyp); } 13307public static object Constant_3_factory(Parser yyp) { return new Constant_3(yyp); }
11104public static object Constant_4_factory(Parser yyp) { return new Constant_4(yyp); } 13308public static object Constant_4_factory(Parser yyp) { return new Constant_4(yyp); }
13309public static object IntArgEvent_5_factory(Parser yyp) { return new IntArgEvent_5(yyp); }
11105public static object BinaryExpression_1_factory(Parser yyp) { return new BinaryExpression_1(yyp); } 13310public static object BinaryExpression_1_factory(Parser yyp) { return new BinaryExpression_1(yyp); }
11106public static object IfStatement_2_factory(Parser yyp) { return new IfStatement_2(yyp); } 13311public static object IfStatement_2_factory(Parser yyp) { return new IfStatement_2(yyp); }
11107public static object IfStatement_3_factory(Parser yyp) { return new IfStatement_3(yyp); } 13312public static object IfStatement_3_factory(Parser yyp) { return new IfStatement_3(yyp); }
11108public static object IfStatement_4_factory(Parser yyp) { return new IfStatement_4(yyp); } 13313public static object KeyArgEvent_factory(Parser yyp) { return new KeyArgEvent(yyp); }
11109public static object ReturnStatement_factory(Parser yyp) { return new ReturnStatement(yyp); }
11110public static object Event_2_factory(Parser yyp) { return new Event_2(yyp); } 13314public static object Event_2_factory(Parser yyp) { return new Event_2(yyp); }
13315public static object JumpLabel_1_factory(Parser yyp) { return new JumpLabel_1(yyp); }
11111public static object RotationConstant_factory(Parser yyp) { return new RotationConstant(yyp); } 13316public static object RotationConstant_factory(Parser yyp) { return new RotationConstant(yyp); }
11112public static object Statement_12_factory(Parser yyp) { return new Statement_12(yyp); } 13317public static object Statement_12_factory(Parser yyp) { return new Statement_12(yyp); }
13318public static object Statement_13_factory(Parser yyp) { return new Statement_13(yyp); }
11113public static object UnaryExpression_1_factory(Parser yyp) { return new UnaryExpression_1(yyp); } 13319public static object UnaryExpression_1_factory(Parser yyp) { return new UnaryExpression_1(yyp); }
11114public static object UnaryExpression_2_factory(Parser yyp) { return new UnaryExpression_2(yyp); } 13320public static object UnaryExpression_2_factory(Parser yyp) { return new UnaryExpression_2(yyp); }
11115public static object UnaryExpression_3_factory(Parser yyp) { return new UnaryExpression_3(yyp); } 13321public static object UnaryExpression_3_factory(Parser yyp) { return new UnaryExpression_3(yyp); }
11116public static object ArgumentList_1_factory(Parser yyp) { return new ArgumentList_1(yyp); } 13322public static object ArgumentList_1_factory(Parser yyp) { return new ArgumentList_1(yyp); }
11117public static object ArgumentList_2_factory(Parser yyp) { return new ArgumentList_2(yyp); } 13323public static object KeyIntIntArgEvent_factory(Parser yyp) { return new KeyIntIntArgEvent(yyp); }
13324public static object ArgumentList_3_factory(Parser yyp) { return new ArgumentList_3(yyp); }
11118public static object Constant_factory(Parser yyp) { return new Constant(yyp); } 13325public static object Constant_factory(Parser yyp) { return new Constant(yyp); }
11119public static object State_factory(Parser yyp) { return new State(yyp); } 13326public static object State_factory(Parser yyp) { return new State(yyp); }
11120public static object Event_13_factory(Parser yyp) { return new Event_13(yyp); } 13327public static object StateBody_13_factory(Parser yyp) { return new StateBody_13(yyp); }
13328public static object KeyArgStateEvent_1_factory(Parser yyp) { return new KeyArgStateEvent_1(yyp); }
13329public static object SimpleAssignment_8_factory(Parser yyp) { return new SimpleAssignment_8(yyp); }
11121public static object LSLProgramRoot_factory(Parser yyp) { return new LSLProgramRoot(yyp); } 13330public static object LSLProgramRoot_factory(Parser yyp) { return new LSLProgramRoot(yyp); }
11122public static object StateChange_factory(Parser yyp) { return new StateChange(yyp); } 13331public static object StateChange_factory(Parser yyp) { return new StateChange(yyp); }
11123public static object IncrementDecrementExpression_2_factory(Parser yyp) { return new IncrementDecrementExpression_2(yyp); } 13332public static object VecDeclaration_1_factory(Parser yyp) { return new VecDeclaration_1(yyp); }
11124public static object GlobalVariableDeclaration_1_factory(Parser yyp) { return new GlobalVariableDeclaration_1(yyp); } 13333public static object GlobalVariableDeclaration_1_factory(Parser yyp) { return new GlobalVariableDeclaration_1(yyp); }
11125public static object GlobalVariableDeclaration_2_factory(Parser yyp) { return new GlobalVariableDeclaration_2(yyp); } 13334public static object GlobalVariableDeclaration_2_factory(Parser yyp) { return new GlobalVariableDeclaration_2(yyp); }
11126public static object IncrementDecrementExpression_5_factory(Parser yyp) { return new IncrementDecrementExpression_5(yyp); } 13335public static object IncrementDecrementExpression_5_factory(Parser yyp) { return new IncrementDecrementExpression_5(yyp); }
11127public static object GlobalFunctionDefinition_2_factory(Parser yyp) { return new GlobalFunctionDefinition_2(yyp); } 13336public static object ReturnStatement_factory(Parser yyp) { return new ReturnStatement(yyp); }
11128public static object IncrementDecrementExpression_7_factory(Parser yyp) { return new IncrementDecrementExpression_7(yyp); } 13337public static object StateBody_10_factory(Parser yyp) { return new StateBody_10(yyp); }
11129public static object IncrementDecrementExpression_8_factory(Parser yyp) { return new IncrementDecrementExpression_8(yyp); } 13338public static object StateBody_11_factory(Parser yyp) { return new StateBody_11(yyp); }
11130public static object Assignment_1_factory(Parser yyp) { return new Assignment_1(yyp); } 13339public static object StateBody_12_factory(Parser yyp) { return new StateBody_12(yyp); }
11131public static object Event_21_factory(Parser yyp) { return new Event_21(yyp); } 13340public static object IntVecVecArgStateEvent_1_factory(Parser yyp) { return new IntVecVecArgStateEvent_1(yyp); }
11132public static object Event_22_factory(Parser yyp) { return new Event_22(yyp); } 13341public static object KeyDeclaration_factory(Parser yyp) { return new KeyDeclaration(yyp); }
13342public static object IntArgEvent_6_factory(Parser yyp) { return new IntArgEvent_6(yyp); }
13343public static object ArgumentDeclarationList_3_factory(Parser yyp) { return new ArgumentDeclarationList_3(yyp); }
13344public static object ArgumentList_2_factory(Parser yyp) { return new ArgumentList_2(yyp); }
13345public static object IntArgEvent_10_factory(Parser yyp) { return new IntArgEvent_10(yyp); }
11133public static object CompoundStatement_factory(Parser yyp) { return new CompoundStatement(yyp); } 13346public static object CompoundStatement_factory(Parser yyp) { return new CompoundStatement(yyp); }
11134public static object RotationConstant_1_factory(Parser yyp) { return new RotationConstant_1(yyp); } 13347public static object TypecastExpression_3_factory(Parser yyp) { return new TypecastExpression_3(yyp); }
11135public static object TypecastExpression_factory(Parser yyp) { return new TypecastExpression(yyp); } 13348public static object IntArgumentDeclarationList_factory(Parser yyp) { return new IntArgumentDeclarationList(yyp); }
13349public static object ArgumentDeclarationList_4_factory(Parser yyp) { return new ArgumentDeclarationList_4(yyp); }
11136public static object SimpleAssignment_3_factory(Parser yyp) { return new SimpleAssignment_3(yyp); } 13350public static object SimpleAssignment_3_factory(Parser yyp) { return new SimpleAssignment_3(yyp); }
11137public static object SimpleAssignment_4_factory(Parser yyp) { return new SimpleAssignment_4(yyp); } 13351public static object SimpleAssignment_4_factory(Parser yyp) { return new SimpleAssignment_4(yyp); }
11138public static object Statement_1_factory(Parser yyp) { return new Statement_1(yyp); } 13352public static object Statement_1_factory(Parser yyp) { return new Statement_1(yyp); }
11139public static object Statement_2_factory(Parser yyp) { return new Statement_2(yyp); } 13353public static object Statement_2_factory(Parser yyp) { return new Statement_2(yyp); }
11140public static object Statement_3_factory(Parser yyp) { return new Statement_3(yyp); }
11141public static object Statement_4_factory(Parser yyp) { return new Statement_4(yyp); } 13354public static object Statement_4_factory(Parser yyp) { return new Statement_4(yyp); }
11142public static object Statement_5_factory(Parser yyp) { return new Statement_5(yyp); } 13355public static object Statement_5_factory(Parser yyp) { return new Statement_5(yyp); }
11143public static object Statement_6_factory(Parser yyp) { return new Statement_6(yyp); } 13356public static object Statement_6_factory(Parser yyp) { return new Statement_6(yyp); }
11144public static object Statement_7_factory(Parser yyp) { return new Statement_7(yyp); }
11145public static object Statement_8_factory(Parser yyp) { return new Statement_8(yyp); } 13357public static object Statement_8_factory(Parser yyp) { return new Statement_8(yyp); }
11146public static object Statement_9_factory(Parser yyp) { return new Statement_9(yyp); } 13358public static object Statement_9_factory(Parser yyp) { return new Statement_9(yyp); }
11147public static object ExpressionArgument_factory(Parser yyp) { return new ExpressionArgument(yyp); } 13359public static object ExpressionArgument_factory(Parser yyp) { return new ExpressionArgument(yyp); }
@@ -11154,27 +13366,35 @@ public static object StateBody_factory(Parser yyp) { return new StateBody(yyp);
11154public static object Event_7_factory(Parser yyp) { return new Event_7(yyp); } 13366public static object Event_7_factory(Parser yyp) { return new Event_7(yyp); }
11155public static object Event_8_factory(Parser yyp) { return new Event_8(yyp); } 13367public static object Event_8_factory(Parser yyp) { return new Event_8(yyp); }
11156public static object IncrementDecrementExpression_1_factory(Parser yyp) { return new IncrementDecrementExpression_1(yyp); } 13368public static object IncrementDecrementExpression_1_factory(Parser yyp) { return new IncrementDecrementExpression_1(yyp); }
11157public static object IncrementDecrementExpression_3_factory(Parser yyp) { return new IncrementDecrementExpression_3(yyp); } 13369public static object IncrementDecrementExpression_2_factory(Parser yyp) { return new IncrementDecrementExpression_2(yyp); }
13370public static object IntVecVecArgumentDeclarationList_1_factory(Parser yyp) { return new IntVecVecArgumentDeclarationList_1(yyp); }
11158public static object IncrementDecrementExpression_4_factory(Parser yyp) { return new IncrementDecrementExpression_4(yyp); } 13371public static object IncrementDecrementExpression_4_factory(Parser yyp) { return new IncrementDecrementExpression_4(yyp); }
11159public static object IncrementDecrementExpression_6_factory(Parser yyp) { return new IncrementDecrementExpression_6(yyp); } 13372public static object IncrementDecrementExpression_6_factory(Parser yyp) { return new IncrementDecrementExpression_6(yyp); }
13373public static object IncrementDecrementExpression_7_factory(Parser yyp) { return new IncrementDecrementExpression_7(yyp); }
11160public static object StateEvent_factory(Parser yyp) { return new StateEvent(yyp); } 13374public static object StateEvent_factory(Parser yyp) { return new StateEvent(yyp); }
11161public static object Event_20_factory(Parser yyp) { return new Event_20(yyp); } 13375public static object IntArgEvent_3_factory(Parser yyp) { return new IntArgEvent_3(yyp); }
11162public static object Event_23_factory(Parser yyp) { return new Event_23(yyp); } 13376public static object IntArgEvent_4_factory(Parser yyp) { return new IntArgEvent_4(yyp); }
11163public static object Event_24_factory(Parser yyp) { return new Event_24(yyp); } 13377public static object KeyDeclaration_1_factory(Parser yyp) { return new KeyDeclaration_1(yyp); }
11164public static object Event_26_factory(Parser yyp) { return new Event_26(yyp); } 13378public static object Statement_3_factory(Parser yyp) { return new Statement_3(yyp); }
13379public static object IntArgEvent_7_factory(Parser yyp) { return new IntArgEvent_7(yyp); }
13380public static object IntArgEvent_8_factory(Parser yyp) { return new IntArgEvent_8(yyp); }
11165public static object SimpleAssignment_10_factory(Parser yyp) { return new SimpleAssignment_10(yyp); } 13381public static object SimpleAssignment_10_factory(Parser yyp) { return new SimpleAssignment_10(yyp); }
13382public static object StatementList_2_factory(Parser yyp) { return new StatementList_2(yyp); }
13383public static object IntRotRotArgStateEvent_1_factory(Parser yyp) { return new IntRotRotArgStateEvent_1(yyp); }
13384public static object VectorArgEvent_2_factory(Parser yyp) { return new VectorArgEvent_2(yyp); }
11166public static object Event_factory(Parser yyp) { return new Event(yyp); } 13385public static object Event_factory(Parser yyp) { return new Event(yyp); }
11167public static object SimpleAssignment_14_factory(Parser yyp) { return new SimpleAssignment_14(yyp); } 13386public static object SimpleAssignment_14_factory(Parser yyp) { return new SimpleAssignment_14(yyp); }
11168public static object SimpleAssignment_16_factory(Parser yyp) { return new SimpleAssignment_16(yyp); } 13387public static object SimpleAssignment_16_factory(Parser yyp) { return new SimpleAssignment_16(yyp); }
13388public static object SimpleAssignment_17_factory(Parser yyp) { return new SimpleAssignment_17(yyp); }
13389public static object SimpleAssignment_18_factory(Parser yyp) { return new SimpleAssignment_18(yyp); }
11169public static object Statement_10_factory(Parser yyp) { return new Statement_10(yyp); } 13390public static object Statement_10_factory(Parser yyp) { return new Statement_10(yyp); }
11170public static object Statement_11_factory(Parser yyp) { return new Statement_11(yyp); } 13391public static object Statement_11_factory(Parser yyp) { return new Statement_11(yyp); }
11171public static object SimpleAssignment_factory(Parser yyp) { return new SimpleAssignment(yyp); } 13392public static object SimpleAssignment_factory(Parser yyp) { return new SimpleAssignment(yyp); }
11172public static object Statement_13_factory(Parser yyp) { return new Statement_13(yyp); } 13393public static object TypecastExpression_factory(Parser yyp) { return new TypecastExpression(yyp); }
11173public static object Event_15_factory(Parser yyp) { return new Event_15(yyp); } 13394public static object JumpStatement_1_factory(Parser yyp) { return new JumpStatement_1(yyp); }
11174public static object Event_16_factory(Parser yyp) { return new Event_16(yyp); }
11175public static object Event_32_factory(Parser yyp) { return new Event_32(yyp); }
11176public static object Event_34_factory(Parser yyp) { return new Event_34(yyp); }
11177public static object SimpleAssignment_20_factory(Parser yyp) { return new SimpleAssignment_20(yyp); } 13395public static object SimpleAssignment_20_factory(Parser yyp) { return new SimpleAssignment_20(yyp); }
13396public static object Statement_7_factory(Parser yyp) { return new Statement_7(yyp); }
13397public static object SimpleAssignment_23_factory(Parser yyp) { return new SimpleAssignment_23(yyp); }
11178public static object SimpleAssignment_24_factory(Parser yyp) { return new SimpleAssignment_24(yyp); } 13398public static object SimpleAssignment_24_factory(Parser yyp) { return new SimpleAssignment_24(yyp); }
11179public static object SimpleAssignment_1_factory(Parser yyp) { return new SimpleAssignment_1(yyp); } 13399public static object SimpleAssignment_1_factory(Parser yyp) { return new SimpleAssignment_1(yyp); }
11180public static object SimpleAssignment_2_factory(Parser yyp) { return new SimpleAssignment_2(yyp); } 13400public static object SimpleAssignment_2_factory(Parser yyp) { return new SimpleAssignment_2(yyp); }
@@ -11182,67 +13402,79 @@ public static object BinaryExpression_factory(Parser yyp) { return new BinaryExp
11182public static object FunctionCallExpression_factory(Parser yyp) { return new FunctionCallExpression(yyp); } 13402public static object FunctionCallExpression_factory(Parser yyp) { return new FunctionCallExpression(yyp); }
11183public static object SimpleAssignment_6_factory(Parser yyp) { return new SimpleAssignment_6(yyp); } 13403public static object SimpleAssignment_6_factory(Parser yyp) { return new SimpleAssignment_6(yyp); }
11184public static object StateBody_1_factory(Parser yyp) { return new StateBody_1(yyp); } 13404public static object StateBody_1_factory(Parser yyp) { return new StateBody_1(yyp); }
11185public static object StatementList_2_factory(Parser yyp) { return new StatementList_2(yyp); } 13405public static object StateBody_2_factory(Parser yyp) { return new StateBody_2(yyp); }
11186public static object SimpleAssignment_9_factory(Parser yyp) { return new SimpleAssignment_9(yyp); } 13406public static object StateBody_3_factory(Parser yyp) { return new StateBody_3(yyp); }
11187public static object BinaryExpression_15_factory(Parser yyp) { return new BinaryExpression_15(yyp); } 13407public static object StateBody_4_factory(Parser yyp) { return new StateBody_4(yyp); }
11188public static object BinaryExpression_16_factory(Parser yyp) { return new BinaryExpression_16(yyp); } 13408public static object StateBody_5_factory(Parser yyp) { return new StateBody_5(yyp); }
11189public static object BinaryExpression_17_factory(Parser yyp) { return new BinaryExpression_17(yyp); } 13409public static object StateBody_6_factory(Parser yyp) { return new StateBody_6(yyp); }
11190public static object BinaryExpression_18_factory(Parser yyp) { return new BinaryExpression_18(yyp); } 13410public static object StateBody_7_factory(Parser yyp) { return new StateBody_7(yyp); }
11191public static object Event_25_factory(Parser yyp) { return new Event_25(yyp); } 13411public static object StateBody_8_factory(Parser yyp) { return new StateBody_8(yyp); }
11192public static object Event_9_factory(Parser yyp) { return new Event_9(yyp); } 13412public static object StateBody_9_factory(Parser yyp) { return new StateBody_9(yyp); }
11193public static object Statement_factory(Parser yyp) { return new Statement(yyp); } 13413public static object Statement_factory(Parser yyp) { return new Statement(yyp); }
13414public static object IncrementDecrementExpression_3_factory(Parser yyp) { return new IncrementDecrementExpression_3(yyp); }
11194public static object JumpStatement_factory(Parser yyp) { return new JumpStatement(yyp); } 13415public static object JumpStatement_factory(Parser yyp) { return new JumpStatement(yyp); }
11195public static object BinaryExpression_11_factory(Parser yyp) { return new BinaryExpression_11(yyp); } 13416public static object BinaryExpression_11_factory(Parser yyp) { return new BinaryExpression_11(yyp); }
11196public static object BinaryExpression_12_factory(Parser yyp) { return new BinaryExpression_12(yyp); } 13417public static object IntArgEvent_factory(Parser yyp) { return new IntArgEvent(yyp); }
11197public static object BinaryExpression_13_factory(Parser yyp) { return new BinaryExpression_13(yyp); } 13418public static object IncrementDecrementExpression_8_factory(Parser yyp) { return new IncrementDecrementExpression_8(yyp); }
11198public static object BinaryExpression_14_factory(Parser yyp) { return new BinaryExpression_14(yyp); } 13419public static object BinaryExpression_14_factory(Parser yyp) { return new BinaryExpression_14(yyp); }
13420public static object BinaryExpression_15_factory(Parser yyp) { return new BinaryExpression_15(yyp); }
13421public static object BinaryExpression_16_factory(Parser yyp) { return new BinaryExpression_16(yyp); }
11199public static object BinaryExpression_6_factory(Parser yyp) { return new BinaryExpression_6(yyp); } 13422public static object BinaryExpression_6_factory(Parser yyp) { return new BinaryExpression_6(yyp); }
11200public static object BinaryExpression_7_factory(Parser yyp) { return new BinaryExpression_7(yyp); } 13423public static object BinaryExpression_7_factory(Parser yyp) { return new BinaryExpression_7(yyp); }
13424public static object Typename_2_factory(Parser yyp) { return new Typename_2(yyp); }
13425public static object Typename_4_factory(Parser yyp) { return new Typename_4(yyp); }
11201public static object ArgumentList_factory(Parser yyp) { return new ArgumentList(yyp); } 13426public static object ArgumentList_factory(Parser yyp) { return new ArgumentList(yyp); }
11202public static object Event_10_factory(Parser yyp) { return new Event_10(yyp); } 13427public static object BinaryExpression_12_factory(Parser yyp) { return new BinaryExpression_12(yyp); }
11203public static object ConstantExpression_1_factory(Parser yyp) { return new ConstantExpression_1(yyp); } 13428public static object BinaryExpression_13_factory(Parser yyp) { return new BinaryExpression_13(yyp); }
11204public static object Event_12_factory(Parser yyp) { return new Event_12(yyp); } 13429public static object GlobalFunctionDefinition_2_factory(Parser yyp) { return new GlobalFunctionDefinition_2(yyp); }
11205public static object Event_14_factory(Parser yyp) { return new Event_14(yyp); } 13430public static object StateChange_2_factory(Parser yyp) { return new StateChange_2(yyp); }
11206public static object Event_17_factory(Parser yyp) { return new Event_17(yyp); } 13431public static object VoidArgEvent_1_factory(Parser yyp) { return new VoidArgEvent_1(yyp); }
11207public static object Event_18_factory(Parser yyp) { return new Event_18(yyp); }
11208public static object Event_19_factory(Parser yyp) { return new Event_19(yyp); }
11209public static object BinaryExpression_10_factory(Parser yyp) { return new BinaryExpression_10(yyp); } 13432public static object BinaryExpression_10_factory(Parser yyp) { return new BinaryExpression_10(yyp); }
13433public static object VoidArgEvent_5_factory(Parser yyp) { return new VoidArgEvent_5(yyp); }
13434public static object VoidArgEvent_6_factory(Parser yyp) { return new VoidArgEvent_6(yyp); }
13435public static object VoidArgEvent_7_factory(Parser yyp) { return new VoidArgEvent_7(yyp); }
13436public static object VoidArgEvent_8_factory(Parser yyp) { return new VoidArgEvent_8(yyp); }
13437public static object BinaryExpression_17_factory(Parser yyp) { return new BinaryExpression_17(yyp); }
11210public static object StateEvent_1_factory(Parser yyp) { return new StateEvent_1(yyp); } 13438public static object StateEvent_1_factory(Parser yyp) { return new StateEvent_1(yyp); }
11211public static object VectorConstant_factory(Parser yyp) { return new VectorConstant(yyp); } 13439public static object VectorConstant_factory(Parser yyp) { return new VectorConstant(yyp); }
11212public static object EmptyStatement_1_factory(Parser yyp) { return new EmptyStatement_1(yyp); } 13440public static object VectorArgEvent_1_factory(Parser yyp) { return new VectorArgEvent_1(yyp); }
13441public static object IntDeclaration_factory(Parser yyp) { return new IntDeclaration(yyp); }
13442public static object VectorArgEvent_3_factory(Parser yyp) { return new VectorArgEvent_3(yyp); }
11213public static object TypecastExpression_4_factory(Parser yyp) { return new TypecastExpression_4(yyp); } 13443public static object TypecastExpression_4_factory(Parser yyp) { return new TypecastExpression_4(yyp); }
11214public static object TypecastExpression_6_factory(Parser yyp) { return new TypecastExpression_6(yyp); } 13444public static object TypecastExpression_6_factory(Parser yyp) { return new TypecastExpression_6(yyp); }
11215public static object TypecastExpression_7_factory(Parser yyp) { return new TypecastExpression_7(yyp); } 13445public static object TypecastExpression_7_factory(Parser yyp) { return new TypecastExpression_7(yyp); }
11216public static object FunctionCall_factory(Parser yyp) { return new FunctionCall(yyp); } 13446public static object FunctionCall_factory(Parser yyp) { return new FunctionCall(yyp); }
11217public static object Event_27_factory(Parser yyp) { return new Event_27(yyp); }
11218public static object Event_28_factory(Parser yyp) { return new Event_28(yyp); }
11219public static object Event_29_factory(Parser yyp) { return new Event_29(yyp); }
11220public static object ListConstant_1_factory(Parser yyp) { return new ListConstant_1(yyp); } 13447public static object ListConstant_1_factory(Parser yyp) { return new ListConstant_1(yyp); }
13448public static object BinaryExpression_18_factory(Parser yyp) { return new BinaryExpression_18(yyp); }
11221public static object Event_6_factory(Parser yyp) { return new Event_6(yyp); } 13449public static object Event_6_factory(Parser yyp) { return new Event_6(yyp); }
13450public static object KeyArgEvent_2_factory(Parser yyp) { return new KeyArgEvent_2(yyp); }
11222public static object Declaration_1_factory(Parser yyp) { return new Declaration_1(yyp); } 13451public static object Declaration_1_factory(Parser yyp) { return new Declaration_1(yyp); }
13452public static object EmptyStatement_1_factory(Parser yyp) { return new EmptyStatement_1(yyp); }
11223public static object SimpleAssignment_7_factory(Parser yyp) { return new SimpleAssignment_7(yyp); } 13453public static object SimpleAssignment_7_factory(Parser yyp) { return new SimpleAssignment_7(yyp); }
11224public static object ForLoop_factory(Parser yyp) { return new ForLoop(yyp); } 13454public static object ForLoop_factory(Parser yyp) { return new ForLoop(yyp); }
11225public static object ForLoop_2_factory(Parser yyp) { return new ForLoop_2(yyp); } 13455public static object ForLoop_2_factory(Parser yyp) { return new ForLoop_2(yyp); }
11226public static object Event_30_factory(Parser yyp) { return new Event_30(yyp); } 13456public static object KeyIntIntArgStateEvent_1_factory(Parser yyp) { return new KeyIntIntArgStateEvent_1(yyp); }
11227public static object Event_31_factory(Parser yyp) { return new Event_31(yyp); } 13457public static object KeyArgumentDeclarationList_1_factory(Parser yyp) { return new KeyArgumentDeclarationList_1(yyp); }
11228public static object Event_33_factory(Parser yyp) { return new Event_33(yyp); }
11229public static object GlobalFunctionDefinition_1_factory(Parser yyp) { return new GlobalFunctionDefinition_1(yyp); } 13458public static object GlobalFunctionDefinition_1_factory(Parser yyp) { return new GlobalFunctionDefinition_1(yyp); }
11230public static object JumpLabel_1_factory(Parser yyp) { return new JumpLabel_1(yyp); }
11231public static object IfStatement_factory(Parser yyp) { return new IfStatement(yyp); } 13459public static object IfStatement_factory(Parser yyp) { return new IfStatement(yyp); }
11232public static object ForLoopStatement_1_factory(Parser yyp) { return new ForLoopStatement_1(yyp); } 13460public static object ForLoopStatement_1_factory(Parser yyp) { return new ForLoopStatement_1(yyp); }
11233public static object ForLoopStatement_2_factory(Parser yyp) { return new ForLoopStatement_2(yyp); } 13461public static object ForLoopStatement_2_factory(Parser yyp) { return new ForLoopStatement_2(yyp); }
11234public static object ForLoopStatement_3_factory(Parser yyp) { return new ForLoopStatement_3(yyp); } 13462public static object ForLoopStatement_3_factory(Parser yyp) { return new ForLoopStatement_3(yyp); }
11235public static object ArgumentDeclarationList_4_factory(Parser yyp) { return new ArgumentDeclarationList_4(yyp); } 13463public static object IntRotRotArgumentDeclarationList_factory(Parser yyp) { return new IntRotRotArgumentDeclarationList(yyp); }
11236public static object ArgumentDeclarationList_5_factory(Parser yyp) { return new ArgumentDeclarationList_5(yyp); } 13464public static object IntArgEvent_1_factory(Parser yyp) { return new IntArgEvent_1(yyp); }
11237public static object EmptyStatement_factory(Parser yyp) { return new EmptyStatement(yyp); } 13465public static object IntArgEvent_2_factory(Parser yyp) { return new IntArgEvent_2(yyp); }
11238public static object WhileStatement_factory(Parser yyp) { return new WhileStatement(yyp); } 13466public static object WhileStatement_factory(Parser yyp) { return new WhileStatement(yyp); }
11239public static object ForLoop_1_factory(Parser yyp) { return new ForLoop_1(yyp); } 13467public static object ForLoop_1_factory(Parser yyp) { return new ForLoop_1(yyp); }
11240public static object Constant_2_factory(Parser yyp) { return new Constant_2(yyp); } 13468public static object Constant_2_factory(Parser yyp) { return new Constant_2(yyp); }
11241public static object StatementList_factory(Parser yyp) { return new StatementList(yyp); } 13469public static object VoidArgEvent_factory(Parser yyp) { return new VoidArgEvent(yyp); }
11242public static object StateBody_2_factory(Parser yyp) { return new StateBody_2(yyp); } 13470public static object RotDeclaration_factory(Parser yyp) { return new RotDeclaration(yyp); }
13471public static object WhileStatement_1_factory(Parser yyp) { return new WhileStatement_1(yyp); }
11243public static object WhileStatement_2_factory(Parser yyp) { return new WhileStatement_2(yyp); } 13472public static object WhileStatement_2_factory(Parser yyp) { return new WhileStatement_2(yyp); }
13473public static object VectorArgStateEvent_1_factory(Parser yyp) { return new VectorArgStateEvent_1(yyp); }
11244public static object IdentExpression_1_factory(Parser yyp) { return new IdentExpression_1(yyp); } 13474public static object IdentExpression_1_factory(Parser yyp) { return new IdentExpression_1(yyp); }
13475public static object VectorArgumentDeclarationList_factory(Parser yyp) { return new VectorArgumentDeclarationList(yyp); }
11245public static object States_factory(Parser yyp) { return new States(yyp); } 13476public static object States_factory(Parser yyp) { return new States(yyp); }
13477public static object VoidArgStateEvent_factory(Parser yyp) { return new VoidArgStateEvent(yyp); }
11246} 13478}
11247public class LSLSyntax 13479public class LSLSyntax
11248: Parser { 13480: Parser {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
index 48964b6..815d11b 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index a2ac9c5..275b608 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -243,7 +243,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
243 if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op") 243 if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op")
244 { 244 {
245 m_coopTermination = true; 245 m_coopTermination = true;
246 m_coopSleepHandle = new AutoResetEvent(false); 246 m_coopSleepHandle = new XEngineEventWaitHandle(false, EventResetMode.AutoReset);
247 } 247 }
248 } 248 }
249 249
@@ -529,8 +529,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
529 { 529 {
530 File.Delete(savedState); 530 File.Delete(savedState);
531 } 531 }
532 catch(Exception) 532 catch (Exception e)
533 { 533 {
534 m_log.Warn(
535 string.Format(
536 "[SCRIPT INSTANCE]: Could not delete script state {0} for script {1} (id {2}) in part {3} (id {4}) in object {5} in {6}. Exception ",
537 savedState, ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name),
538 e);
534 } 539 }
535 } 540 }
536 541
@@ -568,9 +573,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
568 573
569 public bool Stop(int timeout) 574 public bool Stop(int timeout)
570 { 575 {
571// m_log.DebugFormat( 576 if (DebugLevel >= 1)
572// "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}", 577 m_log.DebugFormat(
573// ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks); 578 "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}",
579 ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks);
574 580
575 IScriptWorkItem workItem; 581 IScriptWorkItem workItem;
576 582
@@ -1216,4 +1222,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1216 Suspended = false; 1222 Suspended = false;
1217 } 1223 }
1218 } 1224 }
1225
1226 /// <summary>
1227 /// Xengine event wait handle.
1228 /// </summary>
1229 /// <remarks>
1230 /// This class exists becase XEngineScriptBase gets a reference to this wait handle. We need to make sure that
1231 /// when scripts are running in different AppDomains the lease does not expire.
1232 /// FIXME: Like LSL_Api, etc., this effectively leaks memory since the GC will never collect it. To avoid this,
1233 /// proper remoting sponsorship needs to be implemented across the board.
1234 /// </remarks>
1235 public class XEngineEventWaitHandle : EventWaitHandle
1236 {
1237 public XEngineEventWaitHandle(bool initialState, EventResetMode mode) : base(initialState, mode) {}
1238
1239 public override Object InitializeLifetimeService()
1240 {
1241 return null;
1242 }
1243 }
1219} 1244}
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index b524a18..4ba0e64 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -371,6 +371,31 @@ namespace OpenSim.Region.ScriptEngine.Shared
371 371
372 #endregion 372 #endregion
373 373
374 #region Methods
375 public Quaternion Normalize()
376 {
377 double length = Math.Sqrt(x * x + y * y + z * z + s * s);
378 if (length < float.Epsilon)
379 {
380 x = 0;
381 y = 0;
382 z = 0;
383 s = 1;
384 }
385 else
386 {
387
388 double invLength = 1.0 / length;
389 x *= invLength;
390 y *= invLength;
391 z *= invLength;
392 s *= invLength;
393 }
394
395 return this;
396 }
397 #endregion
398
374 #region Overriders 399 #region Overriders
375 400
376 public override int GetHashCode() 401 public override int GetHashCode()
@@ -546,21 +571,33 @@ namespace OpenSim.Region.ScriptEngine.Shared
546 571
547 set {m_data = value; } 572 set {m_data = value; }
548 } 573 }
549 // Function to obtain LSL type from an index. This is needed 574
550 // because LSL lists allow for multiple types, and safely 575 /// <summary>
551 // iterating in them requires a type check. 576 /// Obtain LSL type from an index.
577 /// </summary>
578 /// <remarks>
579 /// This is needed because LSL lists allow for multiple types, and safely
580 /// iterating in them requires a type check.
581 /// </remarks>
582 /// <returns></returns>
583 /// <param name='itemIndex'></param>
552 public Type GetLSLListItemType(int itemIndex) 584 public Type GetLSLListItemType(int itemIndex)
553 { 585 {
554 return m_data[itemIndex].GetType(); 586 return m_data[itemIndex].GetType();
555 } 587 }
556 588
557 // Member functions to obtain item as specific types. 589 /// <summary>
558 // For cases where implicit conversions would apply if items 590 /// Obtain float from an index.
559 // were not in a list (e.g. integer to float, but not float 591 /// </summary>
560 // to integer) functions check for alternate types so as to 592 /// <remarks>
561 // down-cast from Object to the correct type. 593 /// For cases where implicit conversions would apply if items
562 // Note: no checks for item index being valid are performed 594 /// were not in a list (e.g. integer to float, but not float
563 595 /// to integer) functions check for alternate types so as to
596 /// down-cast from Object to the correct type.
597 /// Note: no checks for item index being valid are performed
598 /// </remarks>
599 /// <returns></returns>
600 /// <param name='itemIndex'></param>
564 public LSL_Types.LSLFloat GetLSLFloatItem(int itemIndex) 601 public LSL_Types.LSLFloat GetLSLFloatItem(int itemIndex)
565 { 602 {
566 if (m_data[itemIndex] is LSL_Types.LSLInteger) 603 if (m_data[itemIndex] is LSL_Types.LSLInteger)
@@ -591,26 +628,14 @@ namespace OpenSim.Region.ScriptEngine.Shared
591 628
592 public LSL_Types.LSLString GetLSLStringItem(int itemIndex) 629 public LSL_Types.LSLString GetLSLStringItem(int itemIndex)
593 { 630 {
594 if (m_data[itemIndex] is LSL_Types.key) 631 if (m_data[itemIndex] is LSL_Types.key)
595 { 632 {
596 return (LSL_Types.key)m_data[itemIndex]; 633 return (LSL_Types.key)m_data[itemIndex];
597 } 634 }
598 else if (m_data[itemIndex] is String) 635 else
599 { 636 {
600 return new LSL_Types.LSLString((string)m_data[itemIndex]); 637 return new LSL_Types.LSLString(m_data[itemIndex].ToString());
601 } 638 }
602 else if (m_data[itemIndex] is LSL_Types.LSLFloat)
603 {
604 return new LSL_Types.LSLString((LSLFloat)m_data[itemIndex]);
605 }
606 else if (m_data[itemIndex] is LSL_Types.LSLInteger)
607 {
608 return new LSL_Types.LSLString((LSLInteger)m_data[itemIndex]);
609 }
610 else
611 {
612 return (LSL_Types.LSLString)m_data[itemIndex];
613 }
614 } 639 }
615 640
616 public LSL_Types.LSLInteger GetLSLIntegerItem(int itemIndex) 641 public LSL_Types.LSLInteger GetLSLIntegerItem(int itemIndex)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs
index c92bcdb..42d1b3b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
75 { 75 {
76 TestHelpers.InMethod(); 76 TestHelpers.InMethod();
77 77
78 string[] ncLines = { "One", "Two", "Three" }; 78 string[] ncLines = { "One", "Twoè", "Three" };
79 79
80 TaskInventoryItem ncItem 80 TaskInventoryItem ncItem
81 = TaskInventoryHelpers.AddNotecard(m_scene, m_so.RootPart, "nc", "1", "10", string.Join("\n", ncLines)); 81 = TaskInventoryHelpers.AddNotecard(m_scene, m_so.RootPart, "nc", "1", "10", string.Join("\n", ncLines));
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs
new file mode 100644
index 0000000..ed61dc0
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs
@@ -0,0 +1,399 @@
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 OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
40using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
45using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
46using OpenSim.Services.Interfaces;
47using OpenSim.Tests.Common;
48using OpenSim.Tests.Common.Mock;
49using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
50using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
51
52namespace OpenSim.Region.ScriptEngine.Shared.Tests
53{
54 [TestFixture]
55 public class LSL_ApiObjectTests : OpenSimTestCase
56 {
57 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
58 private const float FLOAT_ACCURACY = 0.00005f;
59
60 protected Scene m_scene;
61 protected XEngine.XEngine m_engine;
62
63 [SetUp]
64 public override void SetUp()
65 {
66 base.SetUp();
67
68 IConfigSource initConfigSource = new IniConfigSource();
69 IConfig config = initConfigSource.AddConfig("XEngine");
70 config.Set("Enabled", "true");
71
72 m_scene = new SceneHelpers().SetupScene();
73 SceneHelpers.SetupSceneModules(m_scene, initConfigSource);
74
75 m_engine = new XEngine.XEngine();
76 m_engine.Initialise(initConfigSource);
77 m_engine.AddRegion(m_scene);
78 }
79
80 [Test]
81 public void TestllGetLinkPrimitiveParams()
82 {
83 TestHelpers.InMethod();
84 TestHelpers.EnableLogging();
85
86 UUID ownerId = TestHelpers.ParseTail(0x1);
87
88 SceneObjectGroup grp1 = SceneHelpers.CreateSceneObject(2, ownerId, "grp1-", 0x10);
89 grp1.AbsolutePosition = new Vector3(10, 11, 12);
90 m_scene.AddSceneObject(grp1);
91
92 LSL_Api apiGrp1 = new LSL_Api();
93 apiGrp1.Initialize(m_engine, grp1.RootPart, null, null);
94
95 // Check simple 1 prim case
96 {
97 LSL_List resList
98 = apiGrp1.llGetLinkPrimitiveParams(1, new LSL_List(new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
99
100 Assert.That(resList.Length, Is.EqualTo(1));
101 }
102
103 // Check 2 prim case
104 {
105 LSL_List resList
106 = apiGrp1.llGetLinkPrimitiveParams(
107 1,
108 new LSL_List(
109 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
110 new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
111 new LSL_Integer(2),
112 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
113
114 Assert.That(resList.Length, Is.EqualTo(2));
115 }
116
117 // Check invalid parameters are ignored
118 {
119 LSL_List resList
120 = apiGrp1.llGetLinkPrimitiveParams(3, new LSL_List(new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
121
122 Assert.That(resList.Length, Is.EqualTo(0));
123 }
124
125 // Check all parameters are ignored if an initial bad link is given
126 {
127 LSL_List resList
128 = apiGrp1.llGetLinkPrimitiveParams(
129 3,
130 new LSL_List(
131 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
132 new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
133 new LSL_Integer(1),
134 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
135
136 Assert.That(resList.Length, Is.EqualTo(0));
137 }
138
139 // Check only subsequent parameters are ignored when we hit the first bad link number
140 {
141 LSL_List resList
142 = apiGrp1.llGetLinkPrimitiveParams(
143 1,
144 new LSL_List(
145 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
146 new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
147 new LSL_Integer(3),
148 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
149
150 Assert.That(resList.Length, Is.EqualTo(1));
151 }
152 }
153
154 [Test]
155 // llSetPrimitiveParams and llGetPrimitiveParams test.
156 public void TestllSetPrimitiveParams()
157 {
158 TestHelpers.InMethod();
159
160 // Create Prim1.
161 Scene scene = new SceneHelpers().SetupScene();
162 string obj1Name = "Prim1";
163 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
164 SceneObjectPart part1 =
165 new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default,
166 Vector3.Zero, Quaternion.Identity,
167 Vector3.Zero) { Name = obj1Name, UUID = objUuid };
168 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True);
169
170 LSL_Api apiGrp1 = new LSL_Api();
171 apiGrp1.Initialize(m_engine, part1, null, null);
172
173 // Note that prim hollow check is passed with the other prim params in order to allow the
174 // specification of a different check value from the prim param. A cylinder, prism, sphere,
175 // torus or ring, with a hole shape of square, is limited to a hollow of 70%. Test 5 below
176 // specifies a value of 95% and checks to see if 70% was properly returned.
177
178 // Test a sphere.
179 CheckllSetPrimitiveParams(
180 apiGrp1,
181 "test 1", // Prim test identification string
182 new LSL_Types.Vector3(6.0d, 9.9d, 9.9d), // Prim size
183 ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
184 ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
185 new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
186 0.80f, // Prim hollow
187 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
188 new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
189 0.80f); // Prim hollow check
190
191 // Test a prism.
192 CheckllSetPrimitiveParams(
193 apiGrp1,
194 "test 2", // Prim test identification string
195 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
196 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
197 ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
198 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
199 0.90f, // Prim hollow
200 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
201 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
202 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
203 0.90f); // Prim hollow check
204
205 // Test a box.
206 CheckllSetPrimitiveParams(
207 apiGrp1,
208 "test 3", // Prim test identification string
209 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
210 ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
211 ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
212 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
213 0.95f, // Prim hollow
214 new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
215 new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
216 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
217 0.95f); // Prim hollow check
218
219 // Test a tube.
220 CheckllSetPrimitiveParams(
221 apiGrp1,
222 "test 4", // Prim test identification string
223 new LSL_Types.Vector3(4.2d, 4.2d, 4.2d), // Prim size
224 ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
225 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
226 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
227 0.00f, // Prim hollow
228 new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
229 new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
230 // Expression for y selected to test precision problems during byte
231 // cast in SetPrimitiveShapeParams.
232 new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
233 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
234 // Expression for y selected to test precision problems during sbyte
235 // cast in SetPrimitiveShapeParams.
236 new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
237 1.11f, // Prim revolutions
238 0.88f, // Prim radius
239 0.95f, // Prim skew
240 0.00f); // Prim hollow check
241
242 // Test a prism.
243 CheckllSetPrimitiveParams(
244 apiGrp1,
245 "test 5", // Prim test identification string
246 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
247 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
248 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
249 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
250 0.95f, // Prim hollow
251 // Expression for x selected to test precision problems during sbyte
252 // cast in SetPrimitiveShapeBlockParams.
253 new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
254 // Expression for y selected to test precision problems during sbyte
255 // cast in SetPrimitiveShapeParams.
256 new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
257 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
258 0.70f); // Prim hollow check
259
260 // Test a sculpted prim.
261 CheckllSetPrimitiveParams(
262 apiGrp1,
263 "test 6", // Prim test identification string
264 new LSL_Types.Vector3(2.0d, 2.0d, 2.0d), // Prim size
265 ScriptBaseClass.PRIM_TYPE_SCULPT, // Prim type
266 "be293869-d0d9-0a69-5989-ad27f1946fd4", // Prim map
267 ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE); // Prim sculpt type
268 }
269
270 // Set prim params for a box, cylinder or prism and check results.
271 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
272 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
273 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
274 float primHollowCheck)
275 {
276 // Set the prim params.
277 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
278 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
279 primCut, primHollow, primTwist, primTaper, primShear));
280
281 // Get params for prim to validate settings.
282 LSL_Types.list primParams =
283 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
284
285 // Validate settings.
286 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
287 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
288 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
289 Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
290 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
291 CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
292 Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
293 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
294 CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
295 CheckllSetPrimitiveParamsVector(primTaper, api.llList2Vector(primParams, 6), primTest + " prim taper");
296 CheckllSetPrimitiveParamsVector(primShear, api.llList2Vector(primParams, 7), primTest + " prim shear");
297 }
298
299 // Set prim params for a sphere and check results.
300 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
301 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
302 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
303 {
304 // Set the prim params.
305 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
306 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
307 primCut, primHollow, primTwist, primDimple));
308
309 // Get params for prim to validate settings.
310 LSL_Types.list primParams =
311 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
312
313 // Validate settings.
314 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
315 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
316 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
317 Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
318 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
319 CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
320 Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
321 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
322 CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
323 CheckllSetPrimitiveParamsVector(primDimple, api.llList2Vector(primParams, 6), primTest + " prim dimple");
324 }
325
326 // Set prim params for a torus, tube or ring and check results.
327 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
328 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
329 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
330 LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
331 float primRev, float primRadius, float primSkew, float primHollowCheck)
332 {
333 // Set the prim params.
334 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
335 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
336 primCut, primHollow, primTwist, primHoleSize, primShear, primProfCut,
337 primTaper, primRev, primRadius, primSkew));
338
339 // Get params for prim to validate settings.
340 LSL_Types.list primParams =
341 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
342
343 // Valdate settings.
344 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
345 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
346 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
347 Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
348 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
349 CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
350 Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
351 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
352 CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
353 CheckllSetPrimitiveParamsVector(primHoleSize, api.llList2Vector(primParams, 6), primTest + " prim hole size");
354 CheckllSetPrimitiveParamsVector(primShear, api.llList2Vector(primParams, 7), primTest + " prim shear");
355 CheckllSetPrimitiveParamsVector(primProfCut, api.llList2Vector(primParams, 8), primTest + " prim profile cut");
356 CheckllSetPrimitiveParamsVector(primTaper, api.llList2Vector(primParams, 9), primTest + " prim taper");
357 Assert.AreEqual(primRev, api.llList2Float(primParams, 10), FLOAT_ACCURACY,
358 "TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
359 Assert.AreEqual(primRadius, api.llList2Float(primParams, 11), FLOAT_ACCURACY,
360 "TestllSetPrimitiveParams " + primTest + " prim radius fail");
361 Assert.AreEqual(primSkew, api.llList2Float(primParams, 12), FLOAT_ACCURACY,
362 "TestllSetPrimitiveParams " + primTest + " prim skew fail");
363 }
364
365 // Set prim params for a sculpted prim and check results.
366 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
367 LSL_Types.Vector3 primSize, int primType, string primMap, int primSculptType)
368 {
369 // Set the prim params.
370 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
371 ScriptBaseClass.PRIM_TYPE, primType, primMap, primSculptType));
372
373 // Get params for prim to validate settings.
374 LSL_Types.list primParams =
375 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
376
377 // Validate settings.
378 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
379 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
380 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
381 Assert.AreEqual(primMap, (string)api.llList2String(primParams, 2),
382 "TestllSetPrimitiveParams " + primTest + " prim map check fail");
383 Assert.AreEqual(primSculptType, api.llList2Integer(primParams, 3),
384 "TestllSetPrimitiveParams " + primTest + " prim type scuplt check fail");
385 }
386
387 public void CheckllSetPrimitiveParamsVector(LSL_Types.Vector3 vecCheck, LSL_Types.Vector3 vecReturned, string msg)
388 {
389 // Check each vector component against expected result.
390 Assert.AreEqual(vecCheck.x, vecReturned.x, VECTOR_COMPONENT_ACCURACY,
391 "TestllSetPrimitiveParams " + msg + " vector check fail on x component");
392 Assert.AreEqual(vecCheck.y, vecReturned.y, VECTOR_COMPONENT_ACCURACY,
393 "TestllSetPrimitiveParams " + msg + " vector check fail on y component");
394 Assert.AreEqual(vecCheck.z, vecReturned.z, VECTOR_COMPONENT_ACCURACY,
395 "TestllSetPrimitiveParams " + msg + " vector check fail on z component");
396 }
397
398 }
399} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
index e97ae06..7e3726a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
@@ -47,9 +47,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
47 [TestFixture, LongRunning] 47 [TestFixture, LongRunning]
48 public class LSL_ApiTest 48 public class LSL_ApiTest
49 { 49 {
50 private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
51 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d; 50 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
52 private const float FLOAT_ACCURACY = 0.00005f; 51 private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
53 private LSL_Api m_lslApi; 52 private LSL_Api m_lslApi;
54 53
55 [SetUp] 54 [SetUp]
@@ -255,241 +254,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
255 } 254 }
256 255
257 [Test] 256 [Test]
258 // llSetPrimitiveParams and llGetPrimitiveParams test.
259 public void TestllSetPrimitiveParams()
260 {
261 TestHelpers.InMethod();
262
263 // Create Prim1.
264 Scene scene = new SceneHelpers().SetupScene();
265 string obj1Name = "Prim1";
266 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
267 SceneObjectPart part1 =
268 new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default,
269 Vector3.Zero, Quaternion.Identity,
270 Vector3.Zero) { Name = obj1Name, UUID = objUuid };
271 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True);
272
273 // Note that prim hollow check is passed with the other prim params in order to allow the
274 // specification of a different check value from the prim param. A cylinder, prism, sphere,
275 // torus or ring, with a hole shape of square, is limited to a hollow of 70%. Test 5 below
276 // specifies a value of 95% and checks to see if 70% was properly returned.
277
278 // Test a sphere.
279 CheckllSetPrimitiveParams(
280 "test 1", // Prim test identification string
281 new LSL_Types.Vector3(6.0d, 9.9d, 9.9d), // Prim size
282 ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
283 ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
284 new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
285 0.80f, // Prim hollow
286 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
287 new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
288 0.80f); // Prim hollow check
289
290 // Test a prism.
291 CheckllSetPrimitiveParams(
292 "test 2", // Prim test identification string
293 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
294 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
295 ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
296 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
297 0.90f, // Prim hollow
298 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
299 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
300 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
301 0.90f); // Prim hollow check
302
303 // Test a box.
304 CheckllSetPrimitiveParams(
305 "test 3", // Prim test identification string
306 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
307 ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
308 ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
309 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
310 0.95f, // Prim hollow
311 new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
312 new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
313 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
314 0.95f); // Prim hollow check
315
316 // Test a tube.
317 CheckllSetPrimitiveParams(
318 "test 4", // Prim test identification string
319 new LSL_Types.Vector3(4.2d, 4.2d, 4.2d), // Prim size
320 ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
321 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
322 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
323 0.00f, // Prim hollow
324 new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
325 new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
326 // Expression for y selected to test precision problems during byte
327 // cast in SetPrimitiveShapeParams.
328 new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
329 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
330 // Expression for y selected to test precision problems during sbyte
331 // cast in SetPrimitiveShapeParams.
332 new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
333 1.11f, // Prim revolutions
334 0.88f, // Prim radius
335 0.95f, // Prim skew
336 0.00f); // Prim hollow check
337
338 // Test a prism.
339 CheckllSetPrimitiveParams(
340 "test 5", // Prim test identification string
341 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
342 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
343 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
344 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
345 0.95f, // Prim hollow
346 // Expression for x selected to test precision problems during sbyte
347 // cast in SetPrimitiveShapeBlockParams.
348 new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
349 // Expression for y selected to test precision problems during sbyte
350 // cast in SetPrimitiveShapeParams.
351 new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
352 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
353 0.70f); // Prim hollow check
354
355 // Test a sculpted prim.
356 CheckllSetPrimitiveParams(
357 "test 6", // Prim test identification string
358 new LSL_Types.Vector3(2.0d, 2.0d, 2.0d), // Prim size
359 ScriptBaseClass.PRIM_TYPE_SCULPT, // Prim type
360 "be293869-d0d9-0a69-5989-ad27f1946fd4", // Prim map
361 ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE); // Prim sculpt type
362 }
363
364 // Set prim params for a box, cylinder or prism and check results.
365 public void CheckllSetPrimitiveParams(string primTest,
366 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
367 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
368 float primHollowCheck)
369 {
370 // Set the prim params.
371 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
372 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
373 primCut, primHollow, primTwist, primTaper, primShear));
374
375 // Get params for prim to validate settings.
376 LSL_Types.list primParams =
377 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
378
379 // Validate settings.
380 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
381 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
382 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
383 Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
384 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
385 CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
386 Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
387 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
388 CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
389 CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 6), primTest + " prim taper");
390 CheckllSetPrimitiveParamsVector(primShear, m_lslApi.llList2Vector(primParams, 7), primTest + " prim shear");
391 }
392
393 // Set prim params for a sphere and check results.
394 public void CheckllSetPrimitiveParams(string primTest,
395 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
396 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
397 {
398 // Set the prim params.
399 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
400 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
401 primCut, primHollow, primTwist, primDimple));
402
403 // Get params for prim to validate settings.
404 LSL_Types.list primParams =
405 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
406
407 // Validate settings.
408 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
409 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
410 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
411 Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
412 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
413 CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
414 Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
415 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
416 CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
417 CheckllSetPrimitiveParamsVector(primDimple, m_lslApi.llList2Vector(primParams, 6), primTest + " prim dimple");
418 }
419
420 // Set prim params for a torus, tube or ring and check results.
421 public void CheckllSetPrimitiveParams(string primTest,
422 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
423 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
424 LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
425 float primRev, float primRadius, float primSkew, float primHollowCheck)
426 {
427 // Set the prim params.
428 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
429 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
430 primCut, primHollow, primTwist, primHoleSize, primShear, primProfCut,
431 primTaper, primRev, primRadius, primSkew));
432
433 // Get params for prim to validate settings.
434 LSL_Types.list primParams =
435 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
436
437 // Valdate settings.
438 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
439 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
440 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
441 Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
442 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
443 CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
444 Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
445 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
446 CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
447 CheckllSetPrimitiveParamsVector(primHoleSize, m_lslApi.llList2Vector(primParams, 6), primTest + " prim hole size");
448 CheckllSetPrimitiveParamsVector(primShear, m_lslApi.llList2Vector(primParams, 7), primTest + " prim shear");
449 CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut");
450 CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper");
451 Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY,
452 "TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
453 Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY,
454 "TestllSetPrimitiveParams " + primTest + " prim radius fail");
455 Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY,
456 "TestllSetPrimitiveParams " + primTest + " prim skew fail");
457 }
458
459 // Set prim params for a sculpted prim and check results.
460 public void CheckllSetPrimitiveParams(string primTest,
461 LSL_Types.Vector3 primSize, int primType, string primMap, int primSculptType)
462 {
463 // Set the prim params.
464 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
465 ScriptBaseClass.PRIM_TYPE, primType, primMap, primSculptType));
466
467 // Get params for prim to validate settings.
468 LSL_Types.list primParams =
469 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
470
471 // Validate settings.
472 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
473 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
474 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
475 Assert.AreEqual(primMap, (string)m_lslApi.llList2String(primParams, 2),
476 "TestllSetPrimitiveParams " + primTest + " prim map check fail");
477 Assert.AreEqual(primSculptType, m_lslApi.llList2Integer(primParams, 3),
478 "TestllSetPrimitiveParams " + primTest + " prim type scuplt check fail");
479 }
480
481 public void CheckllSetPrimitiveParamsVector(LSL_Types.Vector3 vecCheck, LSL_Types.Vector3 vecReturned, string msg)
482 {
483 // Check each vector component against expected result.
484 Assert.AreEqual(vecCheck.x, vecReturned.x, VECTOR_COMPONENT_ACCURACY,
485 "TestllSetPrimitiveParams " + msg + " vector check fail on x component");
486 Assert.AreEqual(vecCheck.y, vecReturned.y, VECTOR_COMPONENT_ACCURACY,
487 "TestllSetPrimitiveParams " + msg + " vector check fail on y component");
488 Assert.AreEqual(vecCheck.z, vecReturned.z, VECTOR_COMPONENT_ACCURACY,
489 "TestllSetPrimitiveParams " + msg + " vector check fail on z component");
490 }
491
492 [Test]
493 public void TestllVecNorm() 257 public void TestllVecNorm()
494 { 258 {
495 TestHelpers.InMethod(); 259 TestHelpers.InMethod();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
index 74f010e..495e684 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
@@ -180,6 +180,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
180 public void TestOsNpcLoadAppearance() 180 public void TestOsNpcLoadAppearance()
181 { 181 {
182 TestHelpers.InMethod(); 182 TestHelpers.InMethod();
183 //TestHelpers.EnableLogging();
183 184
184 // Store an avatar with a different height from default in a notecard. 185 // Store an avatar with a different height from default in a notecard.
185 UUID userId = TestHelpers.ParseTail(0x1); 186 UUID userId = TestHelpers.ParseTail(0x1);
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
index f0640da..87ea9c4 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 61985e8..2713080 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -551,7 +551,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
551 /// <param name="instance"></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> 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>( 553 private void HandleScriptsAction<TKey>(
554 string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector) 554 string[] cmdparams, Action<IScriptInstance> action, System.Func<IScriptInstance, TKey> keySelector)
555 { 555 {
556 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) 556 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
557 return; 557 return;
@@ -1633,7 +1633,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1633 startInfo.MaxWorkerThreads = maxThreads; 1633 startInfo.MaxWorkerThreads = maxThreads;
1634 startInfo.MinWorkerThreads = minThreads; 1634 startInfo.MinWorkerThreads = minThreads;
1635 startInfo.ThreadPriority = threadPriority;; 1635 startInfo.ThreadPriority = threadPriority;;
1636 startInfo.StackSize = stackSize; 1636 startInfo.MaxStackSize = stackSize;
1637 startInfo.StartSuspended = true; 1637 startInfo.StartSuspended = true;
1638 1638
1639 m_ThreadPool = new SmartThreadPool(startInfo); 1639 m_ThreadPool = new SmartThreadPool(startInfo);
@@ -1827,9 +1827,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1827 public bool GetScriptState(UUID itemID) 1827 public bool GetScriptState(UUID itemID)
1828 { 1828 {
1829 IScriptInstance instance = GetInstance(itemID); 1829 IScriptInstance instance = GetInstance(itemID);
1830 if (instance != null) 1830 return instance != null && instance.Running;
1831 return instance.Running;
1832 return false;
1833 } 1831 }
1834 1832
1835 [DebuggerNonUserCode] 1833 [DebuggerNonUserCode]
@@ -1874,9 +1872,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1874 public DetectParams GetDetectParams(UUID itemID, int idx) 1872 public DetectParams GetDetectParams(UUID itemID, int idx)
1875 { 1873 {
1876 IScriptInstance instance = GetInstance(itemID); 1874 IScriptInstance instance = GetInstance(itemID);
1877 if (instance != null) 1875 return instance != null ? instance.GetDetectParams(idx) : null;
1878 return instance.GetDetectParams(idx);
1879 return null;
1880 } 1876 }
1881 1877
1882 public void SetMinEventDelay(UUID itemID, double delay) 1878 public void SetMinEventDelay(UUID itemID, double delay)
@@ -1889,9 +1885,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1889 public UUID GetDetectID(UUID itemID, int idx) 1885 public UUID GetDetectID(UUID itemID, int idx)
1890 { 1886 {
1891 IScriptInstance instance = GetInstance(itemID); 1887 IScriptInstance instance = GetInstance(itemID);
1892 if (instance != null) 1888 return instance != null ? instance.GetDetectID(idx) : UUID.Zero;
1893 return instance.GetDetectID(idx);
1894 return UUID.Zero;
1895 } 1889 }
1896 1890
1897 [DebuggerNonUserCode] 1891 [DebuggerNonUserCode]
@@ -1906,9 +1900,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1906 public int GetStartParameter(UUID itemID) 1900 public int GetStartParameter(UUID itemID)
1907 { 1901 {
1908 IScriptInstance instance = GetInstance(itemID); 1902 IScriptInstance instance = GetInstance(itemID);
1909 if (instance == null) 1903 return instance == null ? 0 : instance.StartParam;
1910 return 0;
1911 return instance.StartParam;
1912 } 1904 }
1913 1905
1914 public void OnShutdown() 1906 public void OnShutdown()
@@ -1941,9 +1933,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1941 public IScriptApi GetApi(UUID itemID, string name) 1933 public IScriptApi GetApi(UUID itemID, string name)
1942 { 1934 {
1943 IScriptInstance instance = GetInstance(itemID); 1935 IScriptInstance instance = GetInstance(itemID);
1944 if (instance == null) 1936 return instance == null ? null : instance.GetApi(name);
1945 return null;
1946 return instance.GetApi(name);
1947 } 1937 }
1948 1938
1949 public void OnGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) 1939 public void OnGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID)
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
index 8dd7677..9d9dee1 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
@@ -52,16 +52,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
52 return wr.Cancel(); 52 return wr.Cancel();
53 } 53 }
54 54
55 public void Abort() 55 public bool Abort()
56 { 56 {
57 wr.Abort(); 57 return wr.Cancel(true);
58 } 58 }
59 59
60 public bool Wait(int t) 60 public bool Wait(int t)
61 { 61 {
62 // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the 62 // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the
63 // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an 63 // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an
64 // int (32-bit) we can end up with bad values. This occurs on Windows though curious not on Mono 2.10.8 64 // int (32-bit) we can end up with bad values. This occurs on Windows though curiously not on Mono 2.10.8
65 // (or very likely other versions of Mono at least up until 3.0.3). 65 // (or very likely other versions of Mono at least up until 3.0.3).
66 return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false); 66 return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false);
67 } 67 }
diff --git a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
index 1fff12a..f2d3255 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.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33